From 07397df29e57cde5799af16e8f148ae10ed75285 Mon Sep 17 00:00:00 2001 From: Nipun Gupta Date: Sat, 28 Apr 2018 08:21:58 +0530 Subject: dma-mapping: move dma configuration to bus infrastructure ACPI/OF support for configuration of DMA is a bus specific aspect, and thus should be configured by the bus. Introduces a 'dma_configure' bus method so that busses can control their DMA capabilities. Also update the PCI, Platform, ACPI and host1x buses to use the new method. Suggested-by: Christoph Hellwig Signed-off-by: Nipun Gupta Acked-by: Bjorn Helgaas # PCI parts Acked-by: Thierry Reding Reviewed-by: Greg Kroah-Hartman [hch: simplified host1x_dma_configure based on a comment from Thierry, rewrote changelog] Signed-off-by: Christoph Hellwig --- include/linux/device.h | 4 ++++ include/linux/platform_device.h | 2 ++ 2 files changed, 6 insertions(+) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 477956990f5e..63aa672bd394 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -88,6 +88,8 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); * @resume: Called to bring a device on this bus out of sleep mode. * @num_vf: Called to find out how many virtual functions a device on this * bus supports. + * @dma_configure: Called to setup DMA configuration on a device on + this bus. * @pm: Power management operations of this bus, callback the specific * device driver's pm-ops. * @iommu_ops: IOMMU specific operations for this bus, used to attach IOMMU @@ -130,6 +132,8 @@ struct bus_type { int (*num_vf)(struct device *dev); + int (*dma_configure)(struct device *dev); + const struct dev_pm_ops *pm; const struct iommu_ops *iommu_ops; diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 49f634d96118..3097c943fab9 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -356,6 +356,8 @@ extern int platform_pm_restore(struct device *dev); #define platform_pm_restore NULL #endif +extern int platform_dma_configure(struct device *dev); + #ifdef CONFIG_PM_SLEEP #define USE_PLATFORM_PM_SLEEP_OPS \ .suspend = platform_pm_suspend, \ -- cgit v1.2.3-59-g8ed1b From 3d6ce86ee79465e1b1b6e287f8ea26b553fc768e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 3 May 2018 16:25:08 +0200 Subject: drivers: remove force dma flag from buses With each bus implementing its own DMA configuration callback, there is no need for bus to explicitly set the force_dma flag. Modify the of_dma_configure function to accept an input parameter which specifies if implicit DMA configuration is required when it is not described by the firmware. Signed-off-by: Nipun Gupta Acked-by: Bjorn Helgaas # PCI parts Reviewed-by: Rob Herring [hch: tweaked the changelog a bit] Signed-off-by: Christoph Hellwig --- drivers/amba/bus.c | 1 - drivers/base/platform.c | 3 +-- drivers/bcma/main.c | 2 +- drivers/dma/qcom/hidma_mgmt.c | 2 +- drivers/gpu/host1x/bus.c | 5 ++--- drivers/of/device.c | 6 ++++-- drivers/of/of_reserved_mem.c | 2 +- drivers/pci/pci-driver.c | 3 +-- include/linux/device.h | 4 ---- include/linux/of_device.h | 8 ++++++-- 10 files changed, 17 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index b1f41f7d8eeb..3b0118786b43 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -204,7 +204,6 @@ struct bus_type amba_bustype = { .uevent = amba_uevent, .dma_configure = platform_dma_configure, .pm = &amba_pm, - .force_dma = true, }; static int __init amba_init(void) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 638d42e93772..c0ff1e73a634 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1136,7 +1136,7 @@ int platform_dma_configure(struct device *dev) int ret = 0; if (dev->of_node) { - ret = of_dma_configure(dev, dev->of_node); + ret = of_dma_configure(dev, dev->of_node, true); } else if (has_acpi_companion(dev)) { attr = acpi_get_dma_attr(to_acpi_device_node(dev->fwnode)); if (attr != DEV_DMA_NOT_SUPPORTED) @@ -1159,7 +1159,6 @@ struct bus_type platform_bus_type = { .uevent = platform_uevent, .dma_configure = platform_dma_configure, .pm = &platform_dev_pm_ops, - .force_dma = true, }; EXPORT_SYMBOL_GPL(platform_bus_type); diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index e6986c7608f1..fc1f4acdd189 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -207,7 +207,7 @@ static void bcma_of_fill_device(struct device *parent, core->irq = bcma_of_get_irq(parent, core, 0); - of_dma_configure(&core->dev, node); + of_dma_configure(&core->dev, node, false); } unsigned int bcma_core_irq(struct bcma_device *core, int num) diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c index 000c7019ca7d..d64edeb6771a 100644 --- a/drivers/dma/qcom/hidma_mgmt.c +++ b/drivers/dma/qcom/hidma_mgmt.c @@ -398,7 +398,7 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np) } of_node_get(child); new_pdev->dev.of_node = child; - of_dma_configure(&new_pdev->dev, child); + of_dma_configure(&new_pdev->dev, child, true); /* * It is assumed that calling of_msi_configure is safe on * platforms with or without MSI support. diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c index 0c79bafae96c..815bdb42e3f0 100644 --- a/drivers/gpu/host1x/bus.c +++ b/drivers/gpu/host1x/bus.c @@ -316,7 +316,7 @@ static int host1x_device_match(struct device *dev, struct device_driver *drv) static int host1x_dma_configure(struct device *dev) { - return of_dma_configure(dev, dev->of_node); + return of_dma_configure(dev, dev->of_node, true); } static const struct dev_pm_ops host1x_device_pm_ops = { @@ -333,7 +333,6 @@ struct bus_type host1x_bus_type = { .match = host1x_device_match, .dma_configure = host1x_dma_configure, .pm = &host1x_device_pm_ops, - .force_dma = true, }; static void __host1x_device_del(struct host1x_device *device) @@ -422,7 +421,7 @@ static int host1x_device_add(struct host1x *host1x, device->dev.bus = &host1x_bus_type; device->dev.parent = host1x->dev; - of_dma_configure(&device->dev, host1x->dev->of_node); + of_dma_configure(&device->dev, host1x->dev->of_node, true); err = host1x_device_parse_dt(device, driver); if (err < 0) { diff --git a/drivers/of/device.c b/drivers/of/device.c index 064c818105bd..33d85511d790 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -76,6 +76,8 @@ int of_device_add(struct platform_device *ofdev) * of_dma_configure - Setup DMA configuration * @dev: Device to apply DMA configuration * @np: Pointer to OF node having DMA configuration + * @force_dma: Whether device is to be set up by of_dma_configure() even if + * DMA capability is not explicitly described by firmware. * * Try to get devices's DMA configuration from DT and update it * accordingly. @@ -84,7 +86,7 @@ int of_device_add(struct platform_device *ofdev) * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events * to fix up DMA configuration. */ -int of_dma_configure(struct device *dev, struct device_node *np) +int of_dma_configure(struct device *dev, struct device_node *np, bool force_dma) { u64 dma_addr, paddr, size = 0; int ret; @@ -100,7 +102,7 @@ int of_dma_configure(struct device *dev, struct device_node *np) * DMA configuration regardless of whether "dma-ranges" is * correctly specified or not. */ - if (!dev->bus->force_dma) + if (!force_dma) return ret == -ENODEV ? 0 : ret; dma_addr = offset = 0; diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 9a4f4246231d..895c83e0c7b6 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -353,7 +353,7 @@ int of_reserved_mem_device_init_by_idx(struct device *dev, /* ensure that dma_ops is set for virtual devices * using reserved memory */ - of_dma_configure(dev, np); + of_dma_configure(dev, np, true); dev_info(dev, "assigned reserved memory node %s\n", rmem->name); } else { diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index ba8c6b46269e..f8269a725667 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -1595,7 +1595,7 @@ static int pci_dma_configure(struct device *dev) if (IS_ENABLED(CONFIG_OF) && bridge->parent && bridge->parent->of_node) { - ret = of_dma_configure(dev, bridge->parent->of_node); + ret = of_dma_configure(dev, bridge->parent->of_node, true); } else if (has_acpi_companion(bridge)) { struct acpi_device *adev = to_acpi_device_node(bridge->fwnode); enum dev_dma_attr attr = acpi_get_dma_attr(adev); @@ -1621,7 +1621,6 @@ struct bus_type pci_bus_type = { .pm = PCI_PM_OPS_PTR, .num_vf = pci_bus_num_vf, .dma_configure = pci_dma_configure, - .force_dma = true, }; EXPORT_SYMBOL(pci_bus_type); diff --git a/include/linux/device.h b/include/linux/device.h index 63aa672bd394..563077d1cdc1 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -98,8 +98,6 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); * @p: The private data of the driver core, only the driver core can * touch this. * @lock_key: Lock class key for use by the lock validator - * @force_dma: Assume devices on this bus should be set up by dma_configure() - * even if DMA capability is not explicitly described by firmware. * * A bus is a channel between the processor and one or more devices. For the * purposes of the device model, all devices are connected via a bus, even if @@ -140,8 +138,6 @@ struct bus_type { struct subsys_private *p; struct lock_class_key lock_key; - - bool force_dma; }; extern int __must_check bus_register(struct bus_type *bus); diff --git a/include/linux/of_device.h b/include/linux/of_device.h index 8da5a1b31ece..165fd302b442 100644 --- a/include/linux/of_device.h +++ b/include/linux/of_device.h @@ -55,7 +55,9 @@ static inline struct device_node *of_cpu_device_node_get(int cpu) return of_node_get(cpu_dev->of_node); } -int of_dma_configure(struct device *dev, struct device_node *np); +int of_dma_configure(struct device *dev, + struct device_node *np, + bool force_dma); void of_dma_deconfigure(struct device *dev); #else /* CONFIG_OF */ @@ -105,7 +107,9 @@ static inline struct device_node *of_cpu_device_node_get(int cpu) return NULL; } -static inline int of_dma_configure(struct device *dev, struct device_node *np) +static inline int of_dma_configure(struct device *dev, + struct device_node *np, + bool force_dma) { return 0; } -- cgit v1.2.3-59-g8ed1b From 1d3b9917df9725382f4e0005ecaddee114ebc847 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 3 Apr 2018 19:11:46 +0200 Subject: ide: kill ide_toggle_bounce ide_toggle_bounce did select various strange block bounce limits, including not bouncing at all as soon as an iommu is present in the system. Given that the dma_map routines now handle any required bounce buffering except for ISA DMA, and the ide code already must handle either ISA DMA or highmem at least for iommu equipped systems we can get rid of the block layer bounce limit setting entirely. Signed-off-by: Christoph Hellwig Reviewed-by: Jens Axboe --- drivers/ide/ide-dma.c | 2 -- drivers/ide/ide-lib.c | 26 -------------------------- drivers/ide/ide-probe.c | 3 --- include/linux/ide.h | 2 -- 4 files changed, 33 deletions(-) (limited to 'include') diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 54d4d78ca46a..6f344654ef22 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -180,7 +180,6 @@ EXPORT_SYMBOL_GPL(ide_dma_unmap_sg); void ide_dma_off_quietly(ide_drive_t *drive) { drive->dev_flags &= ~IDE_DFLAG_USING_DMA; - ide_toggle_bounce(drive, 0); drive->hwif->dma_ops->dma_host_set(drive, 0); } @@ -211,7 +210,6 @@ EXPORT_SYMBOL(ide_dma_off); void ide_dma_on(ide_drive_t *drive) { drive->dev_flags |= IDE_DFLAG_USING_DMA; - ide_toggle_bounce(drive, 1); drive->hwif->dma_ops->dma_host_set(drive, 1); } diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index e1180fa46196..78cb79eddc8b 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -6,32 +6,6 @@ #include #include -/** - * ide_toggle_bounce - handle bounce buffering - * @drive: drive to update - * @on: on/off boolean - * - * Enable or disable bounce buffering for the device. Drives move - * between PIO and DMA and that changes the rules we need. - */ - -void ide_toggle_bounce(ide_drive_t *drive, int on) -{ - u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */ - - if (!PCI_DMA_BUS_IS_PHYS) { - addr = BLK_BOUNCE_ANY; - } else if (on && drive->media == ide_disk) { - struct device *dev = drive->hwif->dev; - - if (dev && dev->dma_mask) - addr = *dev->dma_mask; - } - - if (drive->queue) - blk_queue_bounce_limit(drive->queue, addr); -} - u64 ide_get_lba_addr(struct ide_cmd *cmd, int lba48) { struct ide_taskfile *tf = &cmd->tf; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 2019e66eada7..8d8ed036ca0a 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -805,9 +805,6 @@ static int ide_init_queue(ide_drive_t *drive) /* assign drive queue */ drive->queue = q; - /* needs drive->queue to be set */ - ide_toggle_bounce(drive, 1); - return 0; } diff --git a/include/linux/ide.h b/include/linux/ide.h index ca9d34feb572..11f0dd03a4b4 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1508,8 +1508,6 @@ static inline void ide_set_hwifdata (ide_hwif_t * hwif, void *data) hwif->hwif_data = data; } -extern void ide_toggle_bounce(ide_drive_t *drive, int on); - u64 ide_get_lba_addr(struct ide_cmd *, int); u8 ide_dump_status(ide_drive_t *, const char *, u8); -- cgit v1.2.3-59-g8ed1b From 325ef1857fff8b2049322921e19421b6c5ad74e5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 12 Apr 2018 09:33:30 +0200 Subject: PCI: remove PCI_DMA_BUS_IS_PHYS This was used by the ide, scsi and networking code in the past to determine if they should bounce payloads. Now that the dma mapping always have to support dma to all physical memory (thanks to swiotlb for non-iommu systems) there is no need to this crude hack any more. Signed-off-by: Christoph Hellwig Acked-by: Palmer Dabbelt (for riscv) Reviewed-by: Jens Axboe --- arch/alpha/include/asm/pci.h | 5 ----- arch/arc/include/asm/pci.h | 6 ------ arch/arm/include/asm/pci.h | 7 ------- arch/arm64/include/asm/pci.h | 5 ----- arch/h8300/include/asm/pci.h | 2 -- arch/hexagon/kernel/dma.c | 1 - arch/ia64/hp/common/sba_iommu.c | 3 --- arch/ia64/include/asm/pci.h | 17 ----------------- arch/ia64/kernel/setup.c | 12 ------------ arch/ia64/sn/kernel/io_common.c | 5 ----- arch/m68k/include/asm/pci.h | 6 ------ arch/microblaze/include/asm/pci.h | 6 ------ arch/mips/include/asm/pci.h | 7 ------- arch/parisc/include/asm/pci.h | 23 ----------------------- arch/parisc/kernel/setup.c | 5 ----- arch/powerpc/include/asm/pci.h | 18 ------------------ arch/riscv/include/asm/pci.h | 3 --- arch/s390/include/asm/pci.h | 2 -- arch/s390/pci/pci_dma.c | 2 -- arch/sh/include/asm/pci.h | 6 ------ arch/sh/kernel/dma-nommu.c | 1 - arch/sparc/include/asm/pci_32.h | 4 ---- arch/sparc/include/asm/pci_64.h | 6 ------ arch/x86/include/asm/pci.h | 3 --- arch/xtensa/include/asm/pci.h | 2 -- drivers/parisc/ccio-dma.c | 2 -- drivers/parisc/sba_iommu.c | 2 -- include/asm-generic/pci.h | 8 -------- include/linux/dma-mapping.h | 1 - lib/dma-direct.c | 1 - tools/virtio/linux/dma-mapping.h | 2 -- 31 files changed, 173 deletions(-) (limited to 'include') diff --git a/arch/alpha/include/asm/pci.h b/arch/alpha/include/asm/pci.h index b9ec55351924..cf6bc1e64d66 100644 --- a/arch/alpha/include/asm/pci.h +++ b/arch/alpha/include/asm/pci.h @@ -56,11 +56,6 @@ struct pci_controller { /* IOMMU controls. */ -/* The PCI address space does not equal the physical memory address space. - The networking and block device layers use this boolean for bounce buffer - decisions. */ -#define PCI_DMA_BUS_IS_PHYS 0 - /* TODO: integrate with include/asm-generic/pci.h ? */ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) { diff --git a/arch/arc/include/asm/pci.h b/arch/arc/include/asm/pci.h index ba56c23c1b20..4ff53c041c64 100644 --- a/arch/arc/include/asm/pci.h +++ b/arch/arc/include/asm/pci.h @@ -16,12 +16,6 @@ #define PCIBIOS_MIN_MEM 0x100000 #define pcibios_assign_all_busses() 1 -/* - * The PCI address space does equal the physical memory address space. - * The networking and block device layers use this boolean for bounce - * buffer decisions. - */ -#define PCI_DMA_BUS_IS_PHYS 1 #endif /* __KERNEL__ */ diff --git a/arch/arm/include/asm/pci.h b/arch/arm/include/asm/pci.h index 1f0de808d111..0abd389cf0ec 100644 --- a/arch/arm/include/asm/pci.h +++ b/arch/arm/include/asm/pci.h @@ -19,13 +19,6 @@ static inline int pci_proc_domain(struct pci_bus *bus) } #endif /* CONFIG_PCI_DOMAINS */ -/* - * The PCI address space does equal the physical memory address space. - * The networking and block device layers use this boolean for bounce - * buffer decisions. - */ -#define PCI_DMA_BUS_IS_PHYS (1) - #define HAVE_PCI_MMAP #define ARCH_GENERIC_PCI_MMAP_RESOURCE diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h index 8747f7c5e0e7..9e690686e8aa 100644 --- a/arch/arm64/include/asm/pci.h +++ b/arch/arm64/include/asm/pci.h @@ -18,11 +18,6 @@ #define pcibios_assign_all_busses() \ (pci_has_flag(PCI_REASSIGN_ALL_BUS)) -/* - * PCI address space differs from physical memory address space - */ -#define PCI_DMA_BUS_IS_PHYS (0) - #define ARCH_GENERIC_PCI_MMAP_RESOURCE 1 extern int isa_dma_bridge_buggy; diff --git a/arch/h8300/include/asm/pci.h b/arch/h8300/include/asm/pci.h index 7c9e55d62215..d4d345a52092 100644 --- a/arch/h8300/include/asm/pci.h +++ b/arch/h8300/include/asm/pci.h @@ -15,6 +15,4 @@ static inline void pcibios_penalize_isa_irq(int irq, int active) /* We don't do dynamic PCI IRQ allocation */ } -#define PCI_DMA_BUS_IS_PHYS (1) - #endif /* _ASM_H8300_PCI_H */ diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c index ad8347c29dcf..77459df34e2e 100644 --- a/arch/hexagon/kernel/dma.c +++ b/arch/hexagon/kernel/dma.c @@ -208,7 +208,6 @@ const struct dma_map_ops hexagon_dma_ops = { .sync_single_for_cpu = hexagon_sync_single_for_cpu, .sync_single_for_device = hexagon_sync_single_for_device, .mapping_error = hexagon_mapping_error, - .is_phys = 1, }; void __init hexagon_dma_init(void) diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c index aec4a3354abe..6f05aba9012f 100644 --- a/arch/ia64/hp/common/sba_iommu.c +++ b/arch/ia64/hp/common/sba_iommu.c @@ -1845,9 +1845,6 @@ static void ioc_init(unsigned long hpa, struct ioc *ioc) ioc_resource_init(ioc); ioc_sac_init(ioc); - if ((long) ~iovp_mask > (long) ia64_max_iommu_merge_mask) - ia64_max_iommu_merge_mask = ~iovp_mask; - printk(KERN_INFO PFX "%s %d.%d HPA 0x%lx IOVA space %dMb at 0x%lx\n", ioc->name, (ioc->rev >> 4) & 0xF, ioc->rev & 0xF, diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h index b1d04e8bafc8..780e8744ba85 100644 --- a/arch/ia64/include/asm/pci.h +++ b/arch/ia64/include/asm/pci.h @@ -30,23 +30,6 @@ struct pci_vector_struct { #define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_MEM 0x10000000 -/* - * PCI_DMA_BUS_IS_PHYS should be set to 1 if there is _necessarily_ a direct - * correspondence between device bus addresses and CPU physical addresses. - * Platforms with a hardware I/O MMU _must_ turn this off to suppress the - * bounce buffer handling code in the block and network device layers. - * Platforms with separate bus address spaces _must_ turn this off and provide - * a device DMA mapping implementation that takes care of the necessary - * address translation. - * - * For now, the ia64 platforms which may have separate/multiple bus address - * spaces all have I/O MMUs which support the merging of physically - * discontiguous buffers, so we can use that as the sole factor to determine - * the setting of PCI_DMA_BUS_IS_PHYS. - */ -extern unsigned long ia64_max_iommu_merge_mask; -#define PCI_DMA_BUS_IS_PHYS (ia64_max_iommu_merge_mask == ~0UL) - #define HAVE_PCI_MMAP #define ARCH_GENERIC_PCI_MMAP_RESOURCE #define arch_can_pci_mmap_wc() 1 diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index dee56bcb993d..ad43cbf70628 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -123,18 +123,6 @@ unsigned long ia64_i_cache_stride_shift = ~0; #define CACHE_STRIDE_SHIFT 5 unsigned long ia64_cache_stride_shift = ~0; -/* - * The merge_mask variable needs to be set to (max(iommu_page_size(iommu)) - 1). This - * mask specifies a mask of address bits that must be 0 in order for two buffers to be - * mergeable by the I/O MMU (i.e., the end address of the first buffer and the start - * address of the second buffer must be aligned to (merge_mask+1) in order to be - * mergeable). By default, we assume there is no I/O MMU which can merge physically - * discontiguous buffers, so we set the merge_mask to ~0UL, which corresponds to a iommu - * page-size of 2^64. - */ -unsigned long ia64_max_iommu_merge_mask = ~0UL; -EXPORT_SYMBOL(ia64_max_iommu_merge_mask); - /* * We use a special marker for the end of memory and it uses the extra (+1) slot */ diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c index 11f2275570fb..8479e9a7ce16 100644 --- a/arch/ia64/sn/kernel/io_common.c +++ b/arch/ia64/sn/kernel/io_common.c @@ -480,11 +480,6 @@ sn_io_early_init(void) tioca_init_provider(); tioce_init_provider(); - /* - * This is needed to avoid bounce limit checks in the blk layer - */ - ia64_max_iommu_merge_mask = ~PAGE_MASK; - sn_irq_lh_init(); INIT_LIST_HEAD(&sn_sysdata_list); sn_init_cpei_timer(); diff --git a/arch/m68k/include/asm/pci.h b/arch/m68k/include/asm/pci.h index ef26fae8cf0b..5a4bc223743b 100644 --- a/arch/m68k/include/asm/pci.h +++ b/arch/m68k/include/asm/pci.h @@ -4,12 +4,6 @@ #include -/* The PCI address space does equal the physical memory - * address space. The networking and block device layers use - * this boolean for bounce buffer decisions. - */ -#define PCI_DMA_BUS_IS_PHYS (1) - #define pcibios_assign_all_busses() 1 #define PCIBIOS_MIN_IO 0x00000100 diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h index 5de871eb4a59..00337861472e 100644 --- a/arch/microblaze/include/asm/pci.h +++ b/arch/microblaze/include/asm/pci.h @@ -62,12 +62,6 @@ extern int pci_mmap_legacy_page_range(struct pci_bus *bus, #define HAVE_PCI_LEGACY 1 -/* The PCI address space does equal the physical memory - * address space (no IOMMU). The IDE and SCSI device layers use - * this boolean for bounce buffer decisions. - */ -#define PCI_DMA_BUS_IS_PHYS (1) - extern void pcibios_claim_one_bus(struct pci_bus *b); extern void pcibios_finish_adding_to_bus(struct pci_bus *bus); diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index 2339f42f047a..436099883022 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h @@ -121,13 +121,6 @@ extern unsigned long PCIBIOS_MIN_MEM; #include #include -/* - * The PCI address space does equal the physical memory address space. - * The networking and block device layers use this boolean for bounce - * buffer decisions. - */ -#define PCI_DMA_BUS_IS_PHYS (1) - #ifdef CONFIG_PCI_DOMAINS_GENERIC static inline int pci_proc_domain(struct pci_bus *bus) { diff --git a/arch/parisc/include/asm/pci.h b/arch/parisc/include/asm/pci.h index 96b7deec512d..3328fd17c19d 100644 --- a/arch/parisc/include/asm/pci.h +++ b/arch/parisc/include/asm/pci.h @@ -87,29 +87,6 @@ struct pci_hba_data { #define PCI_F_EXTEND 0UL #endif /* !CONFIG_64BIT */ -/* - * If the PCI device's view of memory is the same as the CPU's view of memory, - * PCI_DMA_BUS_IS_PHYS is true. The networking and block device layers use - * this boolean for bounce buffer decisions. - */ -#ifdef CONFIG_PA20 -/* All PA-2.0 machines have an IOMMU. */ -#define PCI_DMA_BUS_IS_PHYS 0 -#define parisc_has_iommu() do { } while (0) -#else - -#if defined(CONFIG_IOMMU_CCIO) || defined(CONFIG_IOMMU_SBA) -extern int parisc_bus_is_phys; /* in arch/parisc/kernel/setup.c */ -#define PCI_DMA_BUS_IS_PHYS parisc_bus_is_phys -#define parisc_has_iommu() do { parisc_bus_is_phys = 0; } while (0) -#else -#define PCI_DMA_BUS_IS_PHYS 1 -#define parisc_has_iommu() do { } while (0) -#endif - -#endif /* !CONFIG_PA20 */ - - /* ** Most PCI devices (eg Tulip, NCR720) also export the same registers ** to both MMIO and I/O port space. Due to poor performance of I/O Port diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index 0e9675f857a5..8d3a7b80ac42 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -58,11 +58,6 @@ struct proc_dir_entry * proc_runway_root __read_mostly = NULL; struct proc_dir_entry * proc_gsc_root __read_mostly = NULL; struct proc_dir_entry * proc_mckinley_root __read_mostly = NULL; -#if !defined(CONFIG_PA20) && (defined(CONFIG_IOMMU_CCIO) || defined(CONFIG_IOMMU_SBA)) -int parisc_bus_is_phys __read_mostly = 1; /* Assume no IOMMU is present */ -EXPORT_SYMBOL(parisc_bus_is_phys); -#endif - void __init setup_cmdline(char **cmdline_p) { extern unsigned int boot_args[]; diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h index 401c62aad5e4..2af9ded80540 100644 --- a/arch/powerpc/include/asm/pci.h +++ b/arch/powerpc/include/asm/pci.h @@ -92,24 +92,6 @@ extern int pci_mmap_legacy_page_range(struct pci_bus *bus, #define HAVE_PCI_LEGACY 1 -#ifdef CONFIG_PPC64 - -/* The PCI address space does not equal the physical memory address - * space (we have an IOMMU). The IDE and SCSI device layers use - * this boolean for bounce buffer decisions. - */ -#define PCI_DMA_BUS_IS_PHYS (0) - -#else /* 32-bit */ - -/* The PCI address space does equal the physical memory - * address space (no IOMMU). The IDE and SCSI device layers use - * this boolean for bounce buffer decisions. - */ -#define PCI_DMA_BUS_IS_PHYS (1) - -#endif /* CONFIG_PPC64 */ - extern void pcibios_claim_one_bus(struct pci_bus *b); extern void pcibios_finish_adding_to_bus(struct pci_bus *bus); diff --git a/arch/riscv/include/asm/pci.h b/arch/riscv/include/asm/pci.h index 0f2fc9ef20fc..b3638c505728 100644 --- a/arch/riscv/include/asm/pci.h +++ b/arch/riscv/include/asm/pci.h @@ -26,9 +26,6 @@ /* RISC-V shim does not initialize PCI bus */ #define pcibios_assign_all_busses() 1 -/* We do not have an IOMMU */ -#define PCI_DMA_BUS_IS_PHYS 1 - extern int isa_dma_bridge_buggy; #ifdef CONFIG_PCI diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index 12fe3591034f..94f8db468c9b 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h @@ -2,8 +2,6 @@ #ifndef __ASM_S390_PCI_H #define __ASM_S390_PCI_H -/* must be set before including asm-generic/pci.h */ -#define PCI_DMA_BUS_IS_PHYS (0) /* must be set before including pci_clp.h */ #define PCI_BAR_COUNT 6 diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c index 2d15d84c20ed..10abf5ed6187 100644 --- a/arch/s390/pci/pci_dma.c +++ b/arch/s390/pci/pci_dma.c @@ -685,8 +685,6 @@ const struct dma_map_ops s390_pci_dma_ops = { .map_page = s390_dma_map_pages, .unmap_page = s390_dma_unmap_pages, .mapping_error = s390_mapping_error, - /* if we support direct DMA this must be conditional */ - .is_phys = 0, /* dma_supported is unconditionally true without a callback */ }; EXPORT_SYMBOL_GPL(s390_pci_dma_ops); diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h index 0033f0df2b3b..10a36b1cf2ea 100644 --- a/arch/sh/include/asm/pci.h +++ b/arch/sh/include/asm/pci.h @@ -71,12 +71,6 @@ extern unsigned long PCIBIOS_MIN_IO, PCIBIOS_MIN_MEM; * SuperH has everything mapped statically like x86. */ -/* The PCI address space does equal the physical memory - * address space. The networking and block device layers use - * this boolean for bounce buffer decisions. - */ -#define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys) - #ifdef CONFIG_PCI /* * None of the SH PCI controllers support MWI, it is always treated as a diff --git a/arch/sh/kernel/dma-nommu.c b/arch/sh/kernel/dma-nommu.c index 178457d7620c..3e3a32fc676e 100644 --- a/arch/sh/kernel/dma-nommu.c +++ b/arch/sh/kernel/dma-nommu.c @@ -78,7 +78,6 @@ const struct dma_map_ops nommu_dma_ops = { .sync_single_for_device = nommu_sync_single_for_device, .sync_sg_for_device = nommu_sync_sg_for_device, #endif - .is_phys = 1, }; void __init no_iommu_init(void) diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci_32.h index 98917e48727d..cfc0ee9476c6 100644 --- a/arch/sparc/include/asm/pci_32.h +++ b/arch/sparc/include/asm/pci_32.h @@ -17,10 +17,6 @@ #define PCI_IRQ_NONE 0xffffffff -/* Dynamic DMA mapping stuff. - */ -#define PCI_DMA_BUS_IS_PHYS (0) - #endif /* __KERNEL__ */ #ifndef CONFIG_LEON_PCI diff --git a/arch/sparc/include/asm/pci_64.h b/arch/sparc/include/asm/pci_64.h index 671274e36cfa..fac77813402c 100644 --- a/arch/sparc/include/asm/pci_64.h +++ b/arch/sparc/include/asm/pci_64.h @@ -17,12 +17,6 @@ #define PCI_IRQ_NONE 0xffffffff -/* The PCI address space does not equal the physical memory - * address space. The networking and block device layers use - * this boolean for bounce buffer decisions. - */ -#define PCI_DMA_BUS_IS_PHYS (0) - /* PCI IOMMU mapping bypass support. */ /* PCI 64-bit addressing works for all slots on all controller diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index d32175e30259..662963681ea6 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -117,9 +117,6 @@ void native_restore_msi_irqs(struct pci_dev *dev); #define native_setup_msi_irqs NULL #define native_teardown_msi_irq NULL #endif - -#define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys) - #endif /* __KERNEL__ */ #ifdef CONFIG_X86_64 diff --git a/arch/xtensa/include/asm/pci.h b/arch/xtensa/include/asm/pci.h index d5a82153a7c5..6ddf0a30c60d 100644 --- a/arch/xtensa/include/asm/pci.h +++ b/arch/xtensa/include/asm/pci.h @@ -42,8 +42,6 @@ extern struct pci_controller* pcibios_alloc_controller(void); * decisions. */ -#define PCI_DMA_BUS_IS_PHYS (1) - /* Tell PCI code what kind of PCI resource mappings we support */ #define HAVE_PCI_MMAP 1 #define ARCH_GENERIC_PCI_MMAP_RESOURCE 1 diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index acba1f56af3e..2b129d8525d5 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -1596,8 +1596,6 @@ static int __init ccio_probe(struct parisc_device *dev) } #endif ioc_count++; - - parisc_has_iommu(); return 0; } diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 0a9c762a70fa..a58c586ebd81 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -2017,8 +2017,6 @@ static int __init sba_driver_callback(struct parisc_device *dev) proc_create("sba_iommu", 0, root, &sba_proc_fops); proc_create("sba_iommu-bitmap", 0, root, &sba_proc_bitmap_fops); #endif - - parisc_has_iommu(); return 0; } diff --git a/include/asm-generic/pci.h b/include/asm-generic/pci.h index 830d7659289b..6bb3cd3d695a 100644 --- a/include/asm-generic/pci.h +++ b/include/asm-generic/pci.h @@ -14,12 +14,4 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) } #endif /* HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ */ -/* - * By default, assume that no iommu is in use and that the PCI - * space is mapped to address physical 0. - */ -#ifndef PCI_DMA_BUS_IS_PHYS -#define PCI_DMA_BUS_IS_PHYS (1) -#endif - #endif /* _ASM_GENERIC_PCI_H */ diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index f8ab1c0f589e..a6d4ac8b81e4 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -133,7 +133,6 @@ struct dma_map_ops { #ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK u64 (*get_required_mask)(struct device *dev); #endif - int is_phys; }; extern const struct dma_map_ops dma_direct_ops; diff --git a/lib/dma-direct.c b/lib/dma-direct.c index 970d39155618..df9e726e0712 100644 --- a/lib/dma-direct.c +++ b/lib/dma-direct.c @@ -187,6 +187,5 @@ const struct dma_map_ops dma_direct_ops = { .map_sg = dma_direct_map_sg, .dma_supported = dma_direct_supported, .mapping_error = dma_direct_mapping_error, - .is_phys = 1, }; EXPORT_SYMBOL(dma_direct_ops); diff --git a/tools/virtio/linux/dma-mapping.h b/tools/virtio/linux/dma-mapping.h index 1571e24e9494..f91aeb5fe571 100644 --- a/tools/virtio/linux/dma-mapping.h +++ b/tools/virtio/linux/dma-mapping.h @@ -6,8 +6,6 @@ # error Virtio userspace code does not support CONFIG_HAS_DMA #endif -#define PCI_DMA_BUS_IS_PHYS 1 - enum dma_data_direction { DMA_BIDIRECTIONAL = 0, DMA_TO_DEVICE = 1, -- cgit v1.2.3-59-g8ed1b From 15b28bbcd567a9199481ecfef39702b258f9baff Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 16 Apr 2018 17:22:28 +0200 Subject: dma-debug: move initialization to common code Most mainstream architectures are using 65536 entries, so lets stick to that. If someone is really desperate to override it that can still be done through , but I'd rather see a really good rationale for that. dma_debug_init is now called as a core_initcall, which for many architectures means much earlier, and provides dma-debug functionality earlier in the boot process. This should be safe as it only relies on the memory allocator already being available. Signed-off-by: Christoph Hellwig Acked-by: Marek Szyprowski Reviewed-by: Robin Murphy --- arch/arm/mm/dma-mapping-nommu.c | 9 --------- arch/arm/mm/dma-mapping.c | 9 --------- arch/arm64/mm/dma-mapping.c | 10 ---------- arch/c6x/kernel/dma.c | 11 ----------- arch/ia64/kernel/dma-mapping.c | 10 ---------- arch/microblaze/kernel/dma.c | 11 ----------- arch/mips/mm/dma-default.c | 10 ---------- arch/openrisc/kernel/dma.c | 11 ----------- arch/powerpc/kernel/dma.c | 3 --- arch/s390/pci/pci_dma.c | 9 --------- arch/sh/mm/consistent.c | 9 --------- arch/sparc/kernel/Makefile | 2 -- arch/sparc/kernel/dma.c | 13 ------------- arch/x86/kernel/pci-dma.c | 4 ---- arch/xtensa/kernel/pci-dma.c | 9 --------- include/linux/dma-debug.h | 6 ------ lib/dma-debug.c | 21 ++++++++++++++------- 17 files changed, 14 insertions(+), 143 deletions(-) delete mode 100644 arch/sparc/kernel/dma.c (limited to 'include') diff --git a/arch/arm/mm/dma-mapping-nommu.c b/arch/arm/mm/dma-mapping-nommu.c index 619f24a42d09..f448a0663b10 100644 --- a/arch/arm/mm/dma-mapping-nommu.c +++ b/arch/arm/mm/dma-mapping-nommu.c @@ -241,12 +241,3 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, void arch_teardown_dma_ops(struct device *dev) { } - -#define PREALLOC_DMA_DEBUG_ENTRIES 4096 - -static int __init dma_debug_do_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - return 0; -} -core_initcall(dma_debug_do_init); diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 8c398fedbbb6..c26bf83f44ca 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1165,15 +1165,6 @@ int arm_dma_supported(struct device *dev, u64 mask) return __dma_supported(dev, mask, false); } -#define PREALLOC_DMA_DEBUG_ENTRIES 4096 - -static int __init dma_debug_do_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - return 0; -} -core_initcall(dma_debug_do_init); - #ifdef CONFIG_ARM_DMA_USE_IOMMU static int __dma_info_to_prot(enum dma_data_direction dir, unsigned long attrs) diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index a96ec0181818..db01f2709842 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -508,16 +508,6 @@ static int __init arm64_dma_init(void) } arch_initcall(arm64_dma_init); -#define PREALLOC_DMA_DEBUG_ENTRIES 4096 - -static int __init dma_debug_do_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - return 0; -} -fs_initcall(dma_debug_do_init); - - #ifdef CONFIG_IOMMU_DMA #include #include diff --git a/arch/c6x/kernel/dma.c b/arch/c6x/kernel/dma.c index 9fff8be75f58..31e1a9ec3a9c 100644 --- a/arch/c6x/kernel/dma.c +++ b/arch/c6x/kernel/dma.c @@ -136,14 +136,3 @@ const struct dma_map_ops c6x_dma_ops = { .sync_sg_for_cpu = c6x_dma_sync_sg_for_cpu, }; EXPORT_SYMBOL(c6x_dma_ops); - -/* Number of entries preallocated for DMA-API debugging */ -#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) - -static int __init dma_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - - return 0; -} -fs_initcall(dma_init); diff --git a/arch/ia64/kernel/dma-mapping.c b/arch/ia64/kernel/dma-mapping.c index f2d57e66fd86..7a471d8d67d4 100644 --- a/arch/ia64/kernel/dma-mapping.c +++ b/arch/ia64/kernel/dma-mapping.c @@ -9,16 +9,6 @@ int iommu_detected __read_mostly; const struct dma_map_ops *dma_ops; EXPORT_SYMBOL(dma_ops); -#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) - -static int __init dma_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - - return 0; -} -fs_initcall(dma_init); - const struct dma_map_ops *dma_get_ops(struct device *dev) { return dma_ops; diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c index c91e8cef98dd..3145e7dc8ab1 100644 --- a/arch/microblaze/kernel/dma.c +++ b/arch/microblaze/kernel/dma.c @@ -184,14 +184,3 @@ const struct dma_map_ops dma_nommu_ops = { .sync_sg_for_device = dma_nommu_sync_sg_for_device, }; EXPORT_SYMBOL(dma_nommu_ops); - -/* Number of entries preallocated for DMA-API debugging */ -#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) - -static int __init dma_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - - return 0; -} -fs_initcall(dma_init); diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index dcafa43613b6..f9fef0028ca2 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -402,13 +402,3 @@ static const struct dma_map_ops mips_default_dma_map_ops = { const struct dma_map_ops *mips_dma_map_ops = &mips_default_dma_map_ops; EXPORT_SYMBOL(mips_dma_map_ops); - -#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) - -static int __init mips_dma_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - - return 0; -} -fs_initcall(mips_dma_init); diff --git a/arch/openrisc/kernel/dma.c b/arch/openrisc/kernel/dma.c index a945f00011b4..ec7fd45704d2 100644 --- a/arch/openrisc/kernel/dma.c +++ b/arch/openrisc/kernel/dma.c @@ -247,14 +247,3 @@ const struct dma_map_ops or1k_dma_map_ops = { .sync_single_for_device = or1k_sync_single_for_device, }; EXPORT_SYMBOL(or1k_dma_map_ops); - -/* Number of entries preallocated for DMA-API debugging */ -#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) - -static int __init dma_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - - return 0; -} -fs_initcall(dma_init); diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c index da20569de9d4..138157deeadf 100644 --- a/arch/powerpc/kernel/dma.c +++ b/arch/powerpc/kernel/dma.c @@ -309,8 +309,6 @@ int dma_set_coherent_mask(struct device *dev, u64 mask) } EXPORT_SYMBOL(dma_set_coherent_mask); -#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) - int dma_set_mask(struct device *dev, u64 dma_mask) { if (ppc_md.dma_set_mask) @@ -361,7 +359,6 @@ EXPORT_SYMBOL_GPL(dma_get_required_mask); static int __init dma_init(void) { - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); #ifdef CONFIG_PCI dma_debug_add_bus(&pci_bus_type); #endif diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c index 10abf5ed6187..d387a0fbdd7e 100644 --- a/arch/s390/pci/pci_dma.c +++ b/arch/s390/pci/pci_dma.c @@ -668,15 +668,6 @@ void zpci_dma_exit(void) kmem_cache_destroy(dma_region_table_cache); } -#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) - -static int __init dma_debug_do_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - return 0; -} -fs_initcall(dma_debug_do_init); - const struct dma_map_ops s390_pci_dma_ops = { .alloc = s390_dma_alloc, .free = s390_dma_free, diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c index 8ce98691d822..35ea3099a3b6 100644 --- a/arch/sh/mm/consistent.c +++ b/arch/sh/mm/consistent.c @@ -20,18 +20,9 @@ #include #include -#define PREALLOC_DMA_DEBUG_ENTRIES 4096 - const struct dma_map_ops *dma_ops; EXPORT_SYMBOL(dma_ops); -static int __init dma_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - return 0; -} -fs_initcall(dma_init); - void *dma_generic_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs) diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 76cb57750dda..84cfc5a428d6 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -74,8 +74,6 @@ obj-$(CONFIG_SPARC64) += pcr.o obj-$(CONFIG_SPARC64) += nmi.o obj-$(CONFIG_SPARC64_SMP) += cpumap.o -obj-y += dma.o - obj-$(CONFIG_PCIC_PCI) += pcic.o obj-$(CONFIG_LEON_PCI) += leon_pci.o obj-$(CONFIG_SPARC_GRPCI2)+= leon_pci_grpci2.o diff --git a/arch/sparc/kernel/dma.c b/arch/sparc/kernel/dma.c deleted file mode 100644 index f73e7597c971..000000000000 --- a/arch/sparc/kernel/dma.c +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include - -#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 15) - -static int __init dma_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - return 0; -} -fs_initcall(dma_init); diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 77625b60a510..bcbaa2e8031e 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -55,9 +55,6 @@ struct device x86_dma_fallback_dev = { }; EXPORT_SYMBOL(x86_dma_fallback_dev); -/* Number of entries preallocated for DMA-API debugging */ -#define PREALLOC_DMA_DEBUG_ENTRIES 65536 - void __init pci_iommu_alloc(void) { struct iommu_table_entry *p; @@ -189,7 +186,6 @@ EXPORT_SYMBOL(arch_dma_supported); static int __init pci_iommu_init(void) { struct iommu_table_entry *p; - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); #ifdef CONFIG_PCI dma_debug_add_bus(&pci_bus_type); diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c index 732631ce250f..392b4a80ebc2 100644 --- a/arch/xtensa/kernel/pci-dma.c +++ b/arch/xtensa/kernel/pci-dma.c @@ -261,12 +261,3 @@ const struct dma_map_ops xtensa_dma_map_ops = { .mapping_error = xtensa_dma_mapping_error, }; EXPORT_SYMBOL(xtensa_dma_map_ops); - -#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) - -static int __init xtensa_dma_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - return 0; -} -fs_initcall(xtensa_dma_init); diff --git a/include/linux/dma-debug.h b/include/linux/dma-debug.h index c7d844f09c3a..a785f2507159 100644 --- a/include/linux/dma-debug.h +++ b/include/linux/dma-debug.h @@ -30,8 +30,6 @@ struct bus_type; extern void dma_debug_add_bus(struct bus_type *bus); -extern void dma_debug_init(u32 num_entries); - extern int dma_debug_resize_entries(u32 num_entries); extern void debug_dma_map_page(struct device *dev, struct page *page, @@ -100,10 +98,6 @@ static inline void dma_debug_add_bus(struct bus_type *bus) { } -static inline void dma_debug_init(u32 num_entries) -{ -} - static inline int dma_debug_resize_entries(u32 num_entries) { return 0; diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 7f5cdc1e6b29..712a897174e4 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -41,6 +41,11 @@ #define HASH_FN_SHIFT 13 #define HASH_FN_MASK (HASH_SIZE - 1) +/* allow architectures to override this if absolutely required */ +#ifndef PREALLOC_DMA_DEBUG_ENTRIES +#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) +#endif + enum { dma_debug_single, dma_debug_page, @@ -1004,18 +1009,16 @@ void dma_debug_add_bus(struct bus_type *bus) bus_register_notifier(bus, nb); } -/* - * Let the architectures decide how many entries should be preallocated. - */ -void dma_debug_init(u32 num_entries) +static int dma_debug_init(void) { + u32 num_entries; int i; /* Do not use dma_debug_initialized here, since we really want to be * called to set dma_debug_initialized */ if (global_disable) - return; + return 0; for (i = 0; i < HASH_SIZE; ++i) { INIT_LIST_HEAD(&dma_entry_hash[i].list); @@ -1026,17 +1029,19 @@ void dma_debug_init(u32 num_entries) pr_err("DMA-API: error creating debugfs entries - disabling\n"); global_disable = true; - return; + return 0; } if (req_entries) num_entries = req_entries; + else + num_entries = PREALLOC_DMA_DEBUG_ENTRIES; if (prealloc_memory(num_entries) != 0) { pr_err("DMA-API: debugging out of memory error - disabled\n"); global_disable = true; - return; + return 0; } nr_total_entries = num_free_entries; @@ -1044,7 +1049,9 @@ void dma_debug_init(u32 num_entries) dma_debug_initialized = true; pr_info("DMA-API: debugging enabled by kernel config\n"); + return 0; } +core_initcall(dma_debug_init); static __init int dma_debug_cmdline(char *str) { -- cgit v1.2.3-59-g8ed1b From 0d3fdb157fd0b96b06be7f1d8cea21dd2bc030da Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 3 Apr 2018 15:34:58 +0200 Subject: iommu-common: move to arch/sparc This code is only used by sparc, and all new iommu drivers should use the drivers/iommu/ framework. Also remove the unused exports. Signed-off-by: Christoph Hellwig Acked-by: David S. Miller Reviewed-by: Anshuman Khandual --- arch/sparc/include/asm/iommu-common.h | 53 +++++++ arch/sparc/include/asm/iommu_64.h | 2 +- arch/sparc/kernel/Makefile | 2 +- arch/sparc/kernel/iommu-common.c | 264 +++++++++++++++++++++++++++++++++ arch/sparc/kernel/iommu.c | 2 +- arch/sparc/kernel/ldc.c | 2 +- arch/sparc/kernel/pci_sun4v.c | 2 +- include/linux/iommu-common.h | 53 ------- lib/Makefile | 2 +- lib/iommu-common.c | 267 ---------------------------------- 10 files changed, 323 insertions(+), 326 deletions(-) create mode 100644 arch/sparc/include/asm/iommu-common.h create mode 100644 arch/sparc/kernel/iommu-common.c delete mode 100644 include/linux/iommu-common.h delete mode 100644 lib/iommu-common.c (limited to 'include') diff --git a/arch/sparc/include/asm/iommu-common.h b/arch/sparc/include/asm/iommu-common.h new file mode 100644 index 000000000000..802c90c79d1f --- /dev/null +++ b/arch/sparc/include/asm/iommu-common.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_IOMMU_COMMON_H +#define _LINUX_IOMMU_COMMON_H + +#include +#include +#include + +#define IOMMU_POOL_HASHBITS 4 +#define IOMMU_NR_POOLS (1 << IOMMU_POOL_HASHBITS) +#define IOMMU_ERROR_CODE (~(unsigned long) 0) + +struct iommu_pool { + unsigned long start; + unsigned long end; + unsigned long hint; + spinlock_t lock; +}; + +struct iommu_map_table { + unsigned long table_map_base; + unsigned long table_shift; + unsigned long nr_pools; + void (*lazy_flush)(struct iommu_map_table *); + unsigned long poolsize; + struct iommu_pool pools[IOMMU_NR_POOLS]; + u32 flags; +#define IOMMU_HAS_LARGE_POOL 0x00000001 +#define IOMMU_NO_SPAN_BOUND 0x00000002 +#define IOMMU_NEED_FLUSH 0x00000004 + struct iommu_pool large_pool; + unsigned long *map; +}; + +extern void iommu_tbl_pool_init(struct iommu_map_table *iommu, + unsigned long num_entries, + u32 table_shift, + void (*lazy_flush)(struct iommu_map_table *), + bool large_pool, u32 npools, + bool skip_span_boundary_check); + +extern unsigned long iommu_tbl_range_alloc(struct device *dev, + struct iommu_map_table *iommu, + unsigned long npages, + unsigned long *handle, + unsigned long mask, + unsigned int align_order); + +extern void iommu_tbl_range_free(struct iommu_map_table *iommu, + u64 dma_addr, unsigned long npages, + unsigned long entry); + +#endif diff --git a/arch/sparc/include/asm/iommu_64.h b/arch/sparc/include/asm/iommu_64.h index 9ed6b54caa4b..0ef6dedf747e 100644 --- a/arch/sparc/include/asm/iommu_64.h +++ b/arch/sparc/include/asm/iommu_64.h @@ -17,7 +17,7 @@ #define IOPTE_WRITE 0x0000000000000002UL #define IOMMU_NUM_CTXS 4096 -#include +#include struct iommu_arena { unsigned long *map; diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 84cfc5a428d6..cf8640841b7a 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -59,7 +59,7 @@ obj-$(CONFIG_SPARC32) += leon_pmc.o obj-$(CONFIG_SPARC64) += reboot.o obj-$(CONFIG_SPARC64) += sysfs.o -obj-$(CONFIG_SPARC64) += iommu.o +obj-$(CONFIG_SPARC64) += iommu.o iommu-common.o obj-$(CONFIG_SPARC64) += central.o obj-$(CONFIG_SPARC64) += starfire.o obj-$(CONFIG_SPARC64) += power.o diff --git a/arch/sparc/kernel/iommu-common.c b/arch/sparc/kernel/iommu-common.c new file mode 100644 index 000000000000..59cb16691322 --- /dev/null +++ b/arch/sparc/kernel/iommu-common.c @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * IOMMU mmap management and range allocation functions. + * Based almost entirely upon the powerpc iommu allocator. + */ + +#include +#include +#include +#include +#include +#include +#include + +static unsigned long iommu_large_alloc = 15; + +static DEFINE_PER_CPU(unsigned int, iommu_hash_common); + +static inline bool need_flush(struct iommu_map_table *iommu) +{ + return ((iommu->flags & IOMMU_NEED_FLUSH) != 0); +} + +static inline void set_flush(struct iommu_map_table *iommu) +{ + iommu->flags |= IOMMU_NEED_FLUSH; +} + +static inline void clear_flush(struct iommu_map_table *iommu) +{ + iommu->flags &= ~IOMMU_NEED_FLUSH; +} + +static void setup_iommu_pool_hash(void) +{ + unsigned int i; + static bool do_once; + + if (do_once) + return; + do_once = true; + for_each_possible_cpu(i) + per_cpu(iommu_hash_common, i) = hash_32(i, IOMMU_POOL_HASHBITS); +} + +/* + * Initialize iommu_pool entries for the iommu_map_table. `num_entries' + * is the number of table entries. If `large_pool' is set to true, + * the top 1/4 of the table will be set aside for pool allocations + * of more than iommu_large_alloc pages. + */ +void iommu_tbl_pool_init(struct iommu_map_table *iommu, + unsigned long num_entries, + u32 table_shift, + void (*lazy_flush)(struct iommu_map_table *), + bool large_pool, u32 npools, + bool skip_span_boundary_check) +{ + unsigned int start, i; + struct iommu_pool *p = &(iommu->large_pool); + + setup_iommu_pool_hash(); + if (npools == 0) + iommu->nr_pools = IOMMU_NR_POOLS; + else + iommu->nr_pools = npools; + BUG_ON(npools > IOMMU_NR_POOLS); + + iommu->table_shift = table_shift; + iommu->lazy_flush = lazy_flush; + start = 0; + if (skip_span_boundary_check) + iommu->flags |= IOMMU_NO_SPAN_BOUND; + if (large_pool) + iommu->flags |= IOMMU_HAS_LARGE_POOL; + + if (!large_pool) + iommu->poolsize = num_entries/iommu->nr_pools; + else + iommu->poolsize = (num_entries * 3 / 4)/iommu->nr_pools; + for (i = 0; i < iommu->nr_pools; i++) { + spin_lock_init(&(iommu->pools[i].lock)); + iommu->pools[i].start = start; + iommu->pools[i].hint = start; + start += iommu->poolsize; /* start for next pool */ + iommu->pools[i].end = start - 1; + } + if (!large_pool) + return; + /* initialize large_pool */ + spin_lock_init(&(p->lock)); + p->start = start; + p->hint = p->start; + p->end = num_entries; +} + +unsigned long iommu_tbl_range_alloc(struct device *dev, + struct iommu_map_table *iommu, + unsigned long npages, + unsigned long *handle, + unsigned long mask, + unsigned int align_order) +{ + unsigned int pool_hash = __this_cpu_read(iommu_hash_common); + unsigned long n, end, start, limit, boundary_size; + struct iommu_pool *pool; + int pass = 0; + unsigned int pool_nr; + unsigned int npools = iommu->nr_pools; + unsigned long flags; + bool large_pool = ((iommu->flags & IOMMU_HAS_LARGE_POOL) != 0); + bool largealloc = (large_pool && npages > iommu_large_alloc); + unsigned long shift; + unsigned long align_mask = 0; + + if (align_order > 0) + align_mask = ~0ul >> (BITS_PER_LONG - align_order); + + /* Sanity check */ + if (unlikely(npages == 0)) { + WARN_ON_ONCE(1); + return IOMMU_ERROR_CODE; + } + + if (largealloc) { + pool = &(iommu->large_pool); + pool_nr = 0; /* to keep compiler happy */ + } else { + /* pick out pool_nr */ + pool_nr = pool_hash & (npools - 1); + pool = &(iommu->pools[pool_nr]); + } + spin_lock_irqsave(&pool->lock, flags); + + again: + if (pass == 0 && handle && *handle && + (*handle >= pool->start) && (*handle < pool->end)) + start = *handle; + else + start = pool->hint; + + limit = pool->end; + + /* The case below can happen if we have a small segment appended + * to a large, or when the previous alloc was at the very end of + * the available space. If so, go back to the beginning. If a + * flush is needed, it will get done based on the return value + * from iommu_area_alloc() below. + */ + if (start >= limit) + start = pool->start; + shift = iommu->table_map_base >> iommu->table_shift; + if (limit + shift > mask) { + limit = mask - shift + 1; + /* If we're constrained on address range, first try + * at the masked hint to avoid O(n) search complexity, + * but on second pass, start at 0 in pool 0. + */ + if ((start & mask) >= limit || pass > 0) { + spin_unlock(&(pool->lock)); + pool = &(iommu->pools[0]); + spin_lock(&(pool->lock)); + start = pool->start; + } else { + start &= mask; + } + } + + if (dev) + boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, + 1 << iommu->table_shift); + else + boundary_size = ALIGN(1ULL << 32, 1 << iommu->table_shift); + + boundary_size = boundary_size >> iommu->table_shift; + /* + * if the skip_span_boundary_check had been set during init, we set + * things up so that iommu_is_span_boundary() merely checks if the + * (index + npages) < num_tsb_entries + */ + if ((iommu->flags & IOMMU_NO_SPAN_BOUND) != 0) { + shift = 0; + boundary_size = iommu->poolsize * iommu->nr_pools; + } + n = iommu_area_alloc(iommu->map, limit, start, npages, shift, + boundary_size, align_mask); + if (n == -1) { + if (likely(pass == 0)) { + /* First failure, rescan from the beginning. */ + pool->hint = pool->start; + set_flush(iommu); + pass++; + goto again; + } else if (!largealloc && pass <= iommu->nr_pools) { + spin_unlock(&(pool->lock)); + pool_nr = (pool_nr + 1) & (iommu->nr_pools - 1); + pool = &(iommu->pools[pool_nr]); + spin_lock(&(pool->lock)); + pool->hint = pool->start; + set_flush(iommu); + pass++; + goto again; + } else { + /* give up */ + n = IOMMU_ERROR_CODE; + goto bail; + } + } + if (iommu->lazy_flush && + (n < pool->hint || need_flush(iommu))) { + clear_flush(iommu); + iommu->lazy_flush(iommu); + } + + end = n + npages; + pool->hint = end; + + /* Update handle for SG allocations */ + if (handle) + *handle = end; +bail: + spin_unlock_irqrestore(&(pool->lock), flags); + + return n; +} + +static struct iommu_pool *get_pool(struct iommu_map_table *tbl, + unsigned long entry) +{ + struct iommu_pool *p; + unsigned long largepool_start = tbl->large_pool.start; + bool large_pool = ((tbl->flags & IOMMU_HAS_LARGE_POOL) != 0); + + /* The large pool is the last pool at the top of the table */ + if (large_pool && entry >= largepool_start) { + p = &tbl->large_pool; + } else { + unsigned int pool_nr = entry / tbl->poolsize; + + BUG_ON(pool_nr >= tbl->nr_pools); + p = &tbl->pools[pool_nr]; + } + return p; +} + +/* Caller supplies the index of the entry into the iommu map table + * itself when the mapping from dma_addr to the entry is not the + * default addr->entry mapping below. + */ +void iommu_tbl_range_free(struct iommu_map_table *iommu, u64 dma_addr, + unsigned long npages, unsigned long entry) +{ + struct iommu_pool *pool; + unsigned long flags; + unsigned long shift = iommu->table_shift; + + if (entry == IOMMU_ERROR_CODE) /* use default addr->entry mapping */ + entry = (dma_addr - iommu->table_map_base) >> shift; + pool = get_pool(iommu, entry); + + spin_lock_irqsave(&(pool->lock), flags); + bitmap_clear(iommu->map, entry, npages); + spin_unlock_irqrestore(&(pool->lock), flags); +} diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c index b08dc3416f06..40d008b0bd3e 100644 --- a/arch/sparc/kernel/iommu.c +++ b/arch/sparc/kernel/iommu.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #ifdef CONFIG_PCI #include diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c index 86b625f9d8dc..c0fa3ef6cf01 100644 --- a/arch/sparc/kernel/ldc.c +++ b/arch/sparc/kernel/ldc.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c index 249367228c33..565d9ac883d0 100644 --- a/arch/sparc/kernel/pci_sun4v.c +++ b/arch/sparc/kernel/pci_sun4v.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/linux/iommu-common.h b/include/linux/iommu-common.h deleted file mode 100644 index 802c90c79d1f..000000000000 --- a/include/linux/iommu-common.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _LINUX_IOMMU_COMMON_H -#define _LINUX_IOMMU_COMMON_H - -#include -#include -#include - -#define IOMMU_POOL_HASHBITS 4 -#define IOMMU_NR_POOLS (1 << IOMMU_POOL_HASHBITS) -#define IOMMU_ERROR_CODE (~(unsigned long) 0) - -struct iommu_pool { - unsigned long start; - unsigned long end; - unsigned long hint; - spinlock_t lock; -}; - -struct iommu_map_table { - unsigned long table_map_base; - unsigned long table_shift; - unsigned long nr_pools; - void (*lazy_flush)(struct iommu_map_table *); - unsigned long poolsize; - struct iommu_pool pools[IOMMU_NR_POOLS]; - u32 flags; -#define IOMMU_HAS_LARGE_POOL 0x00000001 -#define IOMMU_NO_SPAN_BOUND 0x00000002 -#define IOMMU_NEED_FLUSH 0x00000004 - struct iommu_pool large_pool; - unsigned long *map; -}; - -extern void iommu_tbl_pool_init(struct iommu_map_table *iommu, - unsigned long num_entries, - u32 table_shift, - void (*lazy_flush)(struct iommu_map_table *), - bool large_pool, u32 npools, - bool skip_span_boundary_check); - -extern unsigned long iommu_tbl_range_alloc(struct device *dev, - struct iommu_map_table *iommu, - unsigned long npages, - unsigned long *handle, - unsigned long mask, - unsigned int align_order); - -extern void iommu_tbl_range_free(struct iommu_map_table *iommu, - u64 dma_addr, unsigned long npages, - unsigned long entry); - -#endif diff --git a/lib/Makefile b/lib/Makefile index ce20696d5a92..94203b5eecd4 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -147,7 +147,7 @@ obj-$(CONFIG_AUDIT_GENERIC) += audit.o obj-$(CONFIG_AUDIT_COMPAT_GENERIC) += compat_audit.o obj-$(CONFIG_SWIOTLB) += swiotlb.o -obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o iommu-common.o +obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o obj-$(CONFIG_NOTIFIER_ERROR_INJECTION) += notifier-error-inject.o obj-$(CONFIG_PM_NOTIFIER_ERROR_INJECT) += pm-notifier-error-inject.o diff --git a/lib/iommu-common.c b/lib/iommu-common.c deleted file mode 100644 index 55b00de106b5..000000000000 --- a/lib/iommu-common.c +++ /dev/null @@ -1,267 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * IOMMU mmap management and range allocation functions. - * Based almost entirely upon the powerpc iommu allocator. - */ - -#include -#include -#include -#include -#include -#include -#include - -static unsigned long iommu_large_alloc = 15; - -static DEFINE_PER_CPU(unsigned int, iommu_hash_common); - -static inline bool need_flush(struct iommu_map_table *iommu) -{ - return ((iommu->flags & IOMMU_NEED_FLUSH) != 0); -} - -static inline void set_flush(struct iommu_map_table *iommu) -{ - iommu->flags |= IOMMU_NEED_FLUSH; -} - -static inline void clear_flush(struct iommu_map_table *iommu) -{ - iommu->flags &= ~IOMMU_NEED_FLUSH; -} - -static void setup_iommu_pool_hash(void) -{ - unsigned int i; - static bool do_once; - - if (do_once) - return; - do_once = true; - for_each_possible_cpu(i) - per_cpu(iommu_hash_common, i) = hash_32(i, IOMMU_POOL_HASHBITS); -} - -/* - * Initialize iommu_pool entries for the iommu_map_table. `num_entries' - * is the number of table entries. If `large_pool' is set to true, - * the top 1/4 of the table will be set aside for pool allocations - * of more than iommu_large_alloc pages. - */ -void iommu_tbl_pool_init(struct iommu_map_table *iommu, - unsigned long num_entries, - u32 table_shift, - void (*lazy_flush)(struct iommu_map_table *), - bool large_pool, u32 npools, - bool skip_span_boundary_check) -{ - unsigned int start, i; - struct iommu_pool *p = &(iommu->large_pool); - - setup_iommu_pool_hash(); - if (npools == 0) - iommu->nr_pools = IOMMU_NR_POOLS; - else - iommu->nr_pools = npools; - BUG_ON(npools > IOMMU_NR_POOLS); - - iommu->table_shift = table_shift; - iommu->lazy_flush = lazy_flush; - start = 0; - if (skip_span_boundary_check) - iommu->flags |= IOMMU_NO_SPAN_BOUND; - if (large_pool) - iommu->flags |= IOMMU_HAS_LARGE_POOL; - - if (!large_pool) - iommu->poolsize = num_entries/iommu->nr_pools; - else - iommu->poolsize = (num_entries * 3 / 4)/iommu->nr_pools; - for (i = 0; i < iommu->nr_pools; i++) { - spin_lock_init(&(iommu->pools[i].lock)); - iommu->pools[i].start = start; - iommu->pools[i].hint = start; - start += iommu->poolsize; /* start for next pool */ - iommu->pools[i].end = start - 1; - } - if (!large_pool) - return; - /* initialize large_pool */ - spin_lock_init(&(p->lock)); - p->start = start; - p->hint = p->start; - p->end = num_entries; -} -EXPORT_SYMBOL(iommu_tbl_pool_init); - -unsigned long iommu_tbl_range_alloc(struct device *dev, - struct iommu_map_table *iommu, - unsigned long npages, - unsigned long *handle, - unsigned long mask, - unsigned int align_order) -{ - unsigned int pool_hash = __this_cpu_read(iommu_hash_common); - unsigned long n, end, start, limit, boundary_size; - struct iommu_pool *pool; - int pass = 0; - unsigned int pool_nr; - unsigned int npools = iommu->nr_pools; - unsigned long flags; - bool large_pool = ((iommu->flags & IOMMU_HAS_LARGE_POOL) != 0); - bool largealloc = (large_pool && npages > iommu_large_alloc); - unsigned long shift; - unsigned long align_mask = 0; - - if (align_order > 0) - align_mask = ~0ul >> (BITS_PER_LONG - align_order); - - /* Sanity check */ - if (unlikely(npages == 0)) { - WARN_ON_ONCE(1); - return IOMMU_ERROR_CODE; - } - - if (largealloc) { - pool = &(iommu->large_pool); - pool_nr = 0; /* to keep compiler happy */ - } else { - /* pick out pool_nr */ - pool_nr = pool_hash & (npools - 1); - pool = &(iommu->pools[pool_nr]); - } - spin_lock_irqsave(&pool->lock, flags); - - again: - if (pass == 0 && handle && *handle && - (*handle >= pool->start) && (*handle < pool->end)) - start = *handle; - else - start = pool->hint; - - limit = pool->end; - - /* The case below can happen if we have a small segment appended - * to a large, or when the previous alloc was at the very end of - * the available space. If so, go back to the beginning. If a - * flush is needed, it will get done based on the return value - * from iommu_area_alloc() below. - */ - if (start >= limit) - start = pool->start; - shift = iommu->table_map_base >> iommu->table_shift; - if (limit + shift > mask) { - limit = mask - shift + 1; - /* If we're constrained on address range, first try - * at the masked hint to avoid O(n) search complexity, - * but on second pass, start at 0 in pool 0. - */ - if ((start & mask) >= limit || pass > 0) { - spin_unlock(&(pool->lock)); - pool = &(iommu->pools[0]); - spin_lock(&(pool->lock)); - start = pool->start; - } else { - start &= mask; - } - } - - if (dev) - boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, - 1 << iommu->table_shift); - else - boundary_size = ALIGN(1ULL << 32, 1 << iommu->table_shift); - - boundary_size = boundary_size >> iommu->table_shift; - /* - * if the skip_span_boundary_check had been set during init, we set - * things up so that iommu_is_span_boundary() merely checks if the - * (index + npages) < num_tsb_entries - */ - if ((iommu->flags & IOMMU_NO_SPAN_BOUND) != 0) { - shift = 0; - boundary_size = iommu->poolsize * iommu->nr_pools; - } - n = iommu_area_alloc(iommu->map, limit, start, npages, shift, - boundary_size, align_mask); - if (n == -1) { - if (likely(pass == 0)) { - /* First failure, rescan from the beginning. */ - pool->hint = pool->start; - set_flush(iommu); - pass++; - goto again; - } else if (!largealloc && pass <= iommu->nr_pools) { - spin_unlock(&(pool->lock)); - pool_nr = (pool_nr + 1) & (iommu->nr_pools - 1); - pool = &(iommu->pools[pool_nr]); - spin_lock(&(pool->lock)); - pool->hint = pool->start; - set_flush(iommu); - pass++; - goto again; - } else { - /* give up */ - n = IOMMU_ERROR_CODE; - goto bail; - } - } - if (iommu->lazy_flush && - (n < pool->hint || need_flush(iommu))) { - clear_flush(iommu); - iommu->lazy_flush(iommu); - } - - end = n + npages; - pool->hint = end; - - /* Update handle for SG allocations */ - if (handle) - *handle = end; -bail: - spin_unlock_irqrestore(&(pool->lock), flags); - - return n; -} -EXPORT_SYMBOL(iommu_tbl_range_alloc); - -static struct iommu_pool *get_pool(struct iommu_map_table *tbl, - unsigned long entry) -{ - struct iommu_pool *p; - unsigned long largepool_start = tbl->large_pool.start; - bool large_pool = ((tbl->flags & IOMMU_HAS_LARGE_POOL) != 0); - - /* The large pool is the last pool at the top of the table */ - if (large_pool && entry >= largepool_start) { - p = &tbl->large_pool; - } else { - unsigned int pool_nr = entry / tbl->poolsize; - - BUG_ON(pool_nr >= tbl->nr_pools); - p = &tbl->pools[pool_nr]; - } - return p; -} - -/* Caller supplies the index of the entry into the iommu map table - * itself when the mapping from dma_addr to the entry is not the - * default addr->entry mapping below. - */ -void iommu_tbl_range_free(struct iommu_map_table *iommu, u64 dma_addr, - unsigned long npages, unsigned long entry) -{ - struct iommu_pool *pool; - unsigned long flags; - unsigned long shift = iommu->table_shift; - - if (entry == IOMMU_ERROR_CODE) /* use default addr->entry mapping */ - entry = (dma_addr - iommu->table_map_base) >> shift; - pool = get_pool(iommu, entry); - - spin_lock_irqsave(&(pool->lock), flags); - bitmap_clear(iommu->map, entry, npages); - spin_unlock_irqrestore(&(pool->lock), flags); -} -EXPORT_SYMBOL(iommu_tbl_range_free); -- cgit v1.2.3-59-g8ed1b From 79c1879ee5473e3404469b07f9bccfe6d0814b93 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 3 Apr 2018 15:41:07 +0200 Subject: iommu-helper: mark iommu_is_span_boundary as inline This avoids selecting IOMMU_HELPER just for this function. And we only use it once or twice in normal builds so this often even is a size reduction. Signed-off-by: Christoph Hellwig --- arch/alpha/Kconfig | 3 --- arch/arm/Kconfig | 3 --- arch/arm64/Kconfig | 3 --- arch/ia64/Kconfig | 3 --- arch/mips/cavium-octeon/Kconfig | 4 ---- arch/mips/loongson64/Kconfig | 4 ---- arch/mips/netlogic/Kconfig | 3 --- arch/powerpc/Kconfig | 1 - arch/unicore32/mm/Kconfig | 3 --- arch/x86/Kconfig | 2 +- drivers/parisc/Kconfig | 5 ----- include/linux/iommu-helper.h | 13 ++++++++++--- lib/iommu-helper.c | 12 +----------- 13 files changed, 12 insertions(+), 47 deletions(-) (limited to 'include') diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index b2022885ced8..3ff735a722af 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -345,9 +345,6 @@ config PCI_DOMAINS config PCI_SYSCALL def_bool PCI -config IOMMU_HELPER - def_bool PCI - config ALPHA_NONAME bool depends on ALPHA_BOOK1 || ALPHA_NONAME_CH diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c723d3e375e8..6bbf7b928b4f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1780,9 +1780,6 @@ config SECCOMP config SWIOTLB def_bool y -config IOMMU_HELPER - def_bool SWIOTLB - config PARAVIRT bool "Enable paravirtualization code" help diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 2005e4baaada..a553deb60fc2 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -251,9 +251,6 @@ config SMP config SWIOTLB def_bool y -config IOMMU_HELPER - def_bool SWIOTLB - config KERNEL_MODE_NEON def_bool y diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index f55aec969cfa..ec2a39741f91 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -612,6 +612,3 @@ source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - -config IOMMU_HELPER - def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC || SWIOTLB) diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig index b5eee1a57d6c..647ed158ac98 100644 --- a/arch/mips/cavium-octeon/Kconfig +++ b/arch/mips/cavium-octeon/Kconfig @@ -67,16 +67,12 @@ config CAVIUM_OCTEON_LOCK_L2_MEMCPY help Lock the kernel's implementation of memcpy() into L2. -config IOMMU_HELPER - bool - config NEED_SG_DMA_LENGTH bool config SWIOTLB def_bool y select DMA_DIRECT_OPS - select IOMMU_HELPER select NEED_SG_DMA_LENGTH config OCTEON_ILM diff --git a/arch/mips/loongson64/Kconfig b/arch/mips/loongson64/Kconfig index 72af0c183969..5efb2e63878e 100644 --- a/arch/mips/loongson64/Kconfig +++ b/arch/mips/loongson64/Kconfig @@ -130,9 +130,6 @@ config LOONGSON_UART_BASE default y depends on EARLY_PRINTK || SERIAL_8250 -config IOMMU_HELPER - bool - config NEED_SG_DMA_LENGTH bool @@ -141,7 +138,6 @@ config SWIOTLB default y depends on CPU_LOONGSON3 select DMA_DIRECT_OPS - select IOMMU_HELPER select NEED_SG_DMA_LENGTH select NEED_DMA_MAP_STATE diff --git a/arch/mips/netlogic/Kconfig b/arch/mips/netlogic/Kconfig index 7fcfc7fe9f14..5c5ee0e05a17 100644 --- a/arch/mips/netlogic/Kconfig +++ b/arch/mips/netlogic/Kconfig @@ -83,9 +83,6 @@ endif config NLM_COMMON bool -config IOMMU_HELPER - bool - config NEED_SG_DMA_LENGTH bool diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index d81e0d4f1f68..5cf611f799be 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -483,7 +483,6 @@ config IOMMU_HELPER config SWIOTLB bool "SWIOTLB support" default n - select IOMMU_HELPER ---help--- Support for IO bounce buffering for systems without an IOMMU. This allows us to DMA to the full physical address space on diff --git a/arch/unicore32/mm/Kconfig b/arch/unicore32/mm/Kconfig index e9154a59d561..3f105e00c432 100644 --- a/arch/unicore32/mm/Kconfig +++ b/arch/unicore32/mm/Kconfig @@ -44,9 +44,6 @@ config SWIOTLB def_bool y select DMA_DIRECT_OPS -config IOMMU_HELPER - def_bool SWIOTLB - config NEED_SG_DMA_LENGTH def_bool SWIOTLB diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 13bf2c727524..a43f21e7cfc5 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -934,7 +934,7 @@ config SWIOTLB config IOMMU_HELPER def_bool y - depends on CALGARY_IOMMU || GART_IOMMU || SWIOTLB || AMD_IOMMU + depends on CALGARY_IOMMU || GART_IOMMU config MAXSMP bool "Enable Maximum number of SMP Processors and NUMA Nodes" diff --git a/drivers/parisc/Kconfig b/drivers/parisc/Kconfig index 3a102a84d637..5a48b5606110 100644 --- a/drivers/parisc/Kconfig +++ b/drivers/parisc/Kconfig @@ -103,11 +103,6 @@ config IOMMU_SBA depends on PCI_LBA default PCI_LBA -config IOMMU_HELPER - bool - depends on IOMMU_SBA || IOMMU_CCIO - default y - source "drivers/pcmcia/Kconfig" endmenu diff --git a/include/linux/iommu-helper.h b/include/linux/iommu-helper.h index cb9a9248c8c0..70d01edcbf8b 100644 --- a/include/linux/iommu-helper.h +++ b/include/linux/iommu-helper.h @@ -2,6 +2,7 @@ #ifndef _LINUX_IOMMU_HELPER_H #define _LINUX_IOMMU_HELPER_H +#include #include static inline unsigned long iommu_device_max_index(unsigned long size, @@ -14,9 +15,15 @@ static inline unsigned long iommu_device_max_index(unsigned long size, return size; } -extern int iommu_is_span_boundary(unsigned int index, unsigned int nr, - unsigned long shift, - unsigned long boundary_size); +static inline int iommu_is_span_boundary(unsigned int index, unsigned int nr, + unsigned long shift, unsigned long boundary_size) +{ + BUG_ON(!is_power_of_2(boundary_size)); + + shift = (shift + index) & (boundary_size - 1); + return shift + nr > boundary_size; +} + extern unsigned long iommu_area_alloc(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, unsigned long shift, diff --git a/lib/iommu-helper.c b/lib/iommu-helper.c index ded1703e7e64..92a9f243c0e2 100644 --- a/lib/iommu-helper.c +++ b/lib/iommu-helper.c @@ -4,17 +4,7 @@ */ #include -#include - -int iommu_is_span_boundary(unsigned int index, unsigned int nr, - unsigned long shift, - unsigned long boundary_size) -{ - BUG_ON(!is_power_of_2(boundary_size)); - - shift = (shift + index) & (boundary_size - 1); - return shift + nr > boundary_size; -} +#include unsigned long iommu_area_alloc(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, -- cgit v1.2.3-59-g8ed1b From f616ab59c294b6ea6efa94f6139ea3eda2f52be0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 9 May 2018 06:53:49 +0200 Subject: dma-mapping: move the NEED_DMA_MAP_STATE config symbol to lib/Kconfig This way we have one central definition of it, and user can select it as needed. Note that we now also always select it when CONFIG_DMA_API_DEBUG is select, which fixes some incorrect checks in a few network drivers. Signed-off-by: Christoph Hellwig Reviewed-by: Anshuman Khandual --- arch/alpha/Kconfig | 4 +--- arch/arm/Kconfig | 4 +--- arch/arm64/Kconfig | 4 +--- arch/ia64/Kconfig | 4 +--- arch/mips/Kconfig | 3 --- arch/parisc/Kconfig | 4 +--- arch/s390/Kconfig | 4 +--- arch/sh/Kconfig | 4 +--- arch/sparc/Kconfig | 4 +--- arch/unicore32/Kconfig | 4 +--- arch/x86/Kconfig | 6 ++---- drivers/iommu/Kconfig | 1 + include/linux/dma-mapping.h | 2 +- lib/Kconfig | 3 +++ lib/Kconfig.debug | 1 + 15 files changed, 17 insertions(+), 35 deletions(-) (limited to 'include') diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 8e6a67ecf069..1fd9645b0c67 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -10,6 +10,7 @@ config ALPHA select HAVE_OPROFILE select HAVE_PCSPKR_PLATFORM select HAVE_PERF_EVENTS + select NEED_DMA_MAP_STATE select NEED_SG_DMA_LENGTH select VIRT_TO_BUS select GENERIC_IRQ_PROBE @@ -68,9 +69,6 @@ config ZONE_DMA config ARCH_DMA_ADDR_T_64BIT def_bool y -config NEED_DMA_MAP_STATE - def_bool y - config GENERIC_ISA_DMA bool default y diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0d2930df7580..924ccac1836b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -95,6 +95,7 @@ config ARM select HAVE_VIRT_CPU_ACCOUNTING_GEN select IRQ_FORCED_THREADING select MODULES_USE_ELF_REL + select NEED_DMA_MAP_STATE select NO_BOOTMEM select OF_EARLY_FLATTREE if OF select OF_RESERVED_MEM if OF @@ -220,9 +221,6 @@ config ARCH_MAY_HAVE_PC_FDC config ZONE_DMA bool -config NEED_DMA_MAP_STATE - def_bool y - config ARCH_SUPPORTS_UPROBES def_bool y diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index eab772a51aad..7259ca832120 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -132,6 +132,7 @@ config ARM64 select IRQ_FORCED_THREADING select MODULES_USE_ELF_RELA select MULTI_IRQ_HANDLER + select NEED_DMA_MAP_STATE select NEED_SG_DMA_LENGTH select NO_BOOTMEM select OF @@ -240,9 +241,6 @@ config HAVE_GENERIC_GUP config ARCH_DMA_ADDR_T_64BIT def_bool y -config NEED_DMA_MAP_STATE - def_bool y - config SMP def_bool y diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 5381e46fe21d..7fd94b41b6da 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -53,6 +53,7 @@ config IA64 select MODULES_USE_ELF_RELA select ARCH_USE_CMPXCHG_LOCKREF select HAVE_ARCH_AUDITSYSCALL + select NEED_DMA_MAP_STATE select NEED_SG_DMA_LENGTH default y help @@ -81,9 +82,6 @@ config MMU config ARCH_DMA_ADDR_T_64BIT def_bool y -config NEED_DMA_MAP_STATE - def_bool y - config SWIOTLB bool diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index fa7e9bbfdd96..2f53a486c86a 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1121,9 +1121,6 @@ config DMA_NONCOHERENT bool select NEED_DMA_MAP_STATE -config NEED_DMA_MAP_STATE - bool - config SYS_HAS_EARLY_PRINTK bool diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 89caea87556e..4d8f64d48597 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -51,6 +51,7 @@ config PARISC select GENERIC_CLOCKEVENTS select ARCH_NO_COHERENT_DMA_MMAP select CPU_NO_EFFICIENT_FFS + select NEED_DMA_MAP_STATE select NEED_SG_DMA_LENGTH help @@ -112,9 +113,6 @@ config PM config STACKTRACE_SUPPORT def_bool y -config NEED_DMA_MAP_STATE - def_bool y - config ISA_DMA_API bool diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index a36b4e4e010a..6bdac4c2a64a 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -710,6 +710,7 @@ menuconfig PCI select PCI_MSI select IOMMU_HELPER select IOMMU_SUPPORT + select NEED_DMA_MAP_STATE select NEED_SG_DMA_LENGTH help @@ -735,9 +736,6 @@ config PCI_DOMAINS config HAS_IOMEM def_bool PCI -config NEED_DMA_MAP_STATE - def_bool PCI - config CHSC_SCH def_tristate m prompt "Support for CHSC subchannels" diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index a0f1c4a8a093..7d521926041e 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -49,6 +49,7 @@ config SUPERH select HAVE_ARCH_AUDITSYSCALL select HAVE_FUTEX_CMPXCHG if FUTEX select HAVE_NMI + select NEED_DMA_MAP_STATE select NEED_SG_DMA_LENGTH help @@ -161,9 +162,6 @@ config DMA_COHERENT config DMA_NONCOHERENT def_bool !DMA_COHERENT -config NEED_DMA_MAP_STATE - def_bool DMA_NONCOHERENT - config PGTABLE_LEVELS default 3 if X2TLB default 2 diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index a2f4483d9b6e..304c94b50171 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -43,6 +43,7 @@ config SPARC select ARCH_HAS_SG_CHAIN select CPU_NO_EFFICIENT_FFS select LOCKDEP_SMALL if LOCKDEP + select NEED_DMA_MAP_STATE select NEED_SG_DMA_LENGTH config SPARC32 @@ -143,9 +144,6 @@ config ZONE_DMA bool default y if SPARC32 -config NEED_DMA_MAP_STATE - def_bool y - config GENERIC_ISA_DMA bool default y if SPARC32 diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig index 462e59a7ae78..82195714d20b 100644 --- a/arch/unicore32/Kconfig +++ b/arch/unicore32/Kconfig @@ -19,6 +19,7 @@ config UNICORE32 select ARCH_WANT_FRAME_POINTERS select GENERIC_IOMAP select MODULES_USE_ELF_REL + select NEED_DMA_MAP_STATE help UniCore-32 is 32-bit Instruction Set Architecture, including a series of low-power-consumption RISC chip @@ -61,9 +62,6 @@ config ARCH_MAY_HAVE_PC_FDC config ZONE_DMA def_bool y -config NEED_DMA_MAP_STATE - def_bool y - source "init/Kconfig" source "kernel/Kconfig.freezer" diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 9cbadd6ba27b..06eea9bffecb 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -28,6 +28,7 @@ config X86_64 select ARCH_USE_CMPXCHG_LOCKREF select HAVE_ARCH_SOFT_DIRTY select MODULES_USE_ELF_RELA + select NEED_DMA_MAP_STATE select X86_DEV_DMA_OPS select ARCH_HAS_SYSCALL_WRAPPER @@ -236,10 +237,6 @@ config ARCH_MMAP_RND_COMPAT_BITS_MAX config SBUS bool -config NEED_DMA_MAP_STATE - def_bool y - depends on X86_64 || INTEL_IOMMU || DMA_API_DEBUG || SWIOTLB - config GENERIC_ISA_DMA def_bool y depends on ISA_DMA_API @@ -925,6 +922,7 @@ config CALGARY_IOMMU_ENABLED_BY_DEFAULT # need this always selected by IOMMU for the VIA workaround config SWIOTLB def_bool y if X86_64 + select NEED_DMA_MAP_STATE ---help--- Support for software bounce buffers used on x86-64 systems which don't have a hardware IOMMU. Using this PCI devices diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index df171cb85822..5b714a062fa7 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -146,6 +146,7 @@ config INTEL_IOMMU select DMA_DIRECT_OPS select IOMMU_API select IOMMU_IOVA + select NEED_DMA_MAP_STATE select DMAR_TABLE help DMA remapping (DMAR) devices support enables independent address diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index a6d4ac8b81e4..25a9a2b04f78 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -838,7 +838,7 @@ static inline int dma_mmap_wc(struct device *dev, #define dma_mmap_writecombine dma_mmap_wc #endif -#if defined(CONFIG_NEED_DMA_MAP_STATE) || defined(CONFIG_DMA_API_DEBUG) +#ifdef CONFIG_NEED_DMA_MAP_STATE #define DEFINE_DMA_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME #define DEFINE_DMA_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME #define dma_unmap_addr(PTR, ADDR_NAME) ((PTR)->ADDR_NAME) diff --git a/lib/Kconfig b/lib/Kconfig index aeb7fae16bc2..ce9fa962d59b 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -432,6 +432,9 @@ config SGL_ALLOC config NEED_SG_DMA_LENGTH bool +config NEED_DMA_MAP_STATE + bool + config IOMMU_HELPER bool diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 45100eda1dab..d5175eb7b917 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1634,6 +1634,7 @@ config PROVIDE_OHCI1394_DMA_INIT config DMA_API_DEBUG bool "Enable debugging of DMA-API usage" + select NEED_DMA_MAP_STATE help Enable this option to debug the use of the DMA API by device drivers. With this option you will be able to detect common bugs in device -- cgit v1.2.3-59-g8ed1b From 8e6390795eacf87f717bc755f352f0aa85da5700 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 3 Apr 2018 16:40:54 +0200 Subject: PCI: remove CONFIG_PCI_BUS_ADDR_T_64BIT This symbol is now always identical to CONFIG_ARCH_DMA_ADDR_T_64BIT, so remove it. Signed-off-by: Christoph Hellwig Acked-by: Bjorn Helgaas --- drivers/pci/Kconfig | 4 ---- drivers/pci/bus.c | 4 ++-- include/linux/pci.h | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 34b56a8f8480..29a487f31dae 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -5,10 +5,6 @@ source "drivers/pci/pcie/Kconfig" -config PCI_BUS_ADDR_T_64BIT - def_bool y if (ARCH_DMA_ADDR_T_64BIT || 64BIT) - depends on PCI - config PCI_MSI bool "Message Signaled Interrupts (MSI and MSI-X)" depends on PCI diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index bc2ded4c451f..35b7fc87eac5 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -120,7 +120,7 @@ int devm_request_pci_bus_resources(struct device *dev, EXPORT_SYMBOL_GPL(devm_request_pci_bus_resources); static struct pci_bus_region pci_32_bit = {0, 0xffffffffULL}; -#ifdef CONFIG_PCI_BUS_ADDR_T_64BIT +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT static struct pci_bus_region pci_64_bit = {0, (pci_bus_addr_t) 0xffffffffffffffffULL}; static struct pci_bus_region pci_high = {(pci_bus_addr_t) 0x100000000ULL, @@ -230,7 +230,7 @@ int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, resource_size_t), void *alignf_data) { -#ifdef CONFIG_PCI_BUS_ADDR_T_64BIT +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT int rc; if (res->flags & IORESOURCE_MEM_64) { diff --git a/include/linux/pci.h b/include/linux/pci.h index 73178a2fcee0..55371cb827ad 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -670,7 +670,7 @@ int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn, int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn, int reg, int len, u32 val); -#ifdef CONFIG_PCI_BUS_ADDR_T_64BIT +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT typedef u64 pci_bus_addr_t; #else typedef u32 pci_bus_addr_t; -- cgit v1.2.3-59-g8ed1b From 782e6769c0df744e773dc2acff71c974b3bba4e9 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 16 Apr 2018 15:24:51 +0200 Subject: dma-mapping: provide a generic dma-noncoherent implementation Add a new dma_map_ops implementation that uses dma-direct for the address mapping of streaming mappings, and which requires arch-specific implemenations of coherent allocate/free. Architectures have to provide flushing helpers to ownership trasnfers to the device and/or CPU, and can provide optional implementations of the coherent mmap functionality, and the cache_flush routines for non-coherent long term allocations. Signed-off-by: Christoph Hellwig Tested-by: Alexey Brodkin Acked-by: Vineet Gupta --- MAINTAINERS | 2 + include/asm-generic/dma-mapping.h | 9 ++++ include/linux/dma-direct.h | 7 ++- include/linux/dma-mapping.h | 1 + include/linux/dma-noncoherent.h | 47 ++++++++++++++++++ lib/Kconfig | 20 ++++++++ lib/Makefile | 1 + lib/dma-direct.c | 8 +-- lib/dma-noncoherent.c | 102 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 192 insertions(+), 5 deletions(-) create mode 100644 include/linux/dma-noncoherent.h create mode 100644 lib/dma-noncoherent.c (limited to 'include') diff --git a/MAINTAINERS b/MAINTAINERS index 79bb02ff812f..08d0d15d4958 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4334,12 +4334,14 @@ W: http://git.infradead.org/users/hch/dma-mapping.git S: Supported F: lib/dma-debug.c F: lib/dma-direct.c +F: lib/dma-noncoherent.c F: lib/dma-virt.c F: drivers/base/dma-mapping.c F: drivers/base/dma-coherent.c F: include/asm-generic/dma-mapping.h F: include/linux/dma-direct.h F: include/linux/dma-mapping.h +F: include/linux/dma-noncoherent.h DME1737 HARDWARE MONITOR DRIVER M: Juerg Haefliger diff --git a/include/asm-generic/dma-mapping.h b/include/asm-generic/dma-mapping.h index 880a292d792f..ad2868263867 100644 --- a/include/asm-generic/dma-mapping.h +++ b/include/asm-generic/dma-mapping.h @@ -4,7 +4,16 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) { + /* + * Use the non-coherent ops if available. If an architecture wants a + * more fine-grained selection of operations it will have to implement + * get_arch_dma_ops itself or use the per-device dma_ops. + */ +#ifdef CONFIG_DMA_NONCOHERENT_OPS + return &dma_noncoherent_ops; +#else return &dma_direct_ops; +#endif } #endif /* _ASM_GENERIC_DMA_MAPPING_H */ diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h index 53ad6a47f513..8d9f33febde5 100644 --- a/include/linux/dma-direct.h +++ b/include/linux/dma-direct.h @@ -59,6 +59,11 @@ void *dma_direct_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs); void dma_direct_free(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_addr, unsigned long attrs); +dma_addr_t dma_direct_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, enum dma_data_direction dir, + unsigned long attrs); +int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents, + enum dma_data_direction dir, unsigned long attrs); int dma_direct_supported(struct device *dev, u64 mask); - +int dma_direct_mapping_error(struct device *dev, dma_addr_t dma_addr); #endif /* _LINUX_DMA_DIRECT_H */ diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 25a9a2b04f78..4be070df5fc5 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -136,6 +136,7 @@ struct dma_map_ops { }; extern const struct dma_map_ops dma_direct_ops; +extern const struct dma_map_ops dma_noncoherent_ops; extern const struct dma_map_ops dma_virt_ops; #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) diff --git a/include/linux/dma-noncoherent.h b/include/linux/dma-noncoherent.h new file mode 100644 index 000000000000..10b2654d549b --- /dev/null +++ b/include/linux/dma-noncoherent.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_DMA_NONCOHERENT_H +#define _LINUX_DMA_NONCOHERENT_H 1 + +#include + +void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, + gfp_t gfp, unsigned long attrs); +void arch_dma_free(struct device *dev, size_t size, void *cpu_addr, + dma_addr_t dma_addr, unsigned long attrs); + +#ifdef CONFIG_DMA_NONCOHERENT_MMAP +int arch_dma_mmap(struct device *dev, struct vm_area_struct *vma, + void *cpu_addr, dma_addr_t dma_addr, size_t size, + unsigned long attrs); +#else +#define arch_dma_mmap NULL +#endif /* CONFIG_DMA_NONCOHERENT_MMAP */ + +#ifdef CONFIG_DMA_NONCOHERENT_CACHE_SYNC +void arch_dma_cache_sync(struct device *dev, void *vaddr, size_t size, + enum dma_data_direction direction); +#else +#define arch_dma_cache_sync NULL +#endif /* CONFIG_DMA_NONCOHERENT_CACHE_SYNC */ + +#ifdef CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE +void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr, + size_t size, enum dma_data_direction dir); +#else +static inline void arch_sync_dma_for_device(struct device *dev, + phys_addr_t paddr, size_t size, enum dma_data_direction dir) +{ +} +#endif /* ARCH_HAS_SYNC_DMA_FOR_DEVICE */ + +#ifdef CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU +void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr, + size_t size, enum dma_data_direction dir); +#else +static inline void arch_sync_dma_for_cpu(struct device *dev, + phys_addr_t paddr, size_t size, enum dma_data_direction dir) +{ +} +#endif /* ARCH_HAS_SYNC_DMA_FOR_CPU */ + +#endif /* _LINUX_DMA_NONCOHERENT_H */ diff --git a/lib/Kconfig b/lib/Kconfig index 6c4e9d0ce5d1..7a913937888b 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -441,10 +441,30 @@ config ARCH_DMA_ADDR_T_64BIT config IOMMU_HELPER bool +config ARCH_HAS_SYNC_DMA_FOR_DEVICE + bool + +config ARCH_HAS_SYNC_DMA_FOR_CPU + bool + select NEED_DMA_MAP_STATE + config DMA_DIRECT_OPS bool depends on HAS_DMA +config DMA_NONCOHERENT_OPS + bool + depends on HAS_DMA + select DMA_DIRECT_OPS + +config DMA_NONCOHERENT_MMAP + bool + depends on DMA_NONCOHERENT_OPS + +config DMA_NONCOHERENT_CACHE_SYNC + bool + depends on DMA_NONCOHERENT_OPS + config DMA_VIRT_OPS bool depends on HAS_DMA diff --git a/lib/Makefile b/lib/Makefile index 94203b5eecd4..9f18c8152281 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -30,6 +30,7 @@ lib-$(CONFIG_PRINTK) += dump_stack.o lib-$(CONFIG_MMU) += ioremap.o lib-$(CONFIG_SMP) += cpumask.o lib-$(CONFIG_DMA_DIRECT_OPS) += dma-direct.o +lib-$(CONFIG_DMA_NONCOHERENT_OPS) += dma-noncoherent.o lib-$(CONFIG_DMA_VIRT_OPS) += dma-virt.o lib-y += kobject.o klist.o diff --git a/lib/dma-direct.c b/lib/dma-direct.c index df9e726e0712..b824eb218782 100644 --- a/lib/dma-direct.c +++ b/lib/dma-direct.c @@ -128,7 +128,7 @@ void dma_direct_free(struct device *dev, size_t size, void *cpu_addr, free_pages((unsigned long)cpu_addr, page_order); } -static dma_addr_t dma_direct_map_page(struct device *dev, struct page *page, +dma_addr_t dma_direct_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction dir, unsigned long attrs) { @@ -139,8 +139,8 @@ static dma_addr_t dma_direct_map_page(struct device *dev, struct page *page, return dma_addr; } -static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, - int nents, enum dma_data_direction dir, unsigned long attrs) +int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents, + enum dma_data_direction dir, unsigned long attrs) { int i; struct scatterlist *sg; @@ -175,7 +175,7 @@ int dma_direct_supported(struct device *dev, u64 mask) return 1; } -static int dma_direct_mapping_error(struct device *dev, dma_addr_t dma_addr) +int dma_direct_mapping_error(struct device *dev, dma_addr_t dma_addr) { return dma_addr == DIRECT_MAPPING_ERROR; } diff --git a/lib/dma-noncoherent.c b/lib/dma-noncoherent.c new file mode 100644 index 000000000000..79e9a757387f --- /dev/null +++ b/lib/dma-noncoherent.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Christoph Hellwig. + * + * DMA operations that map physical memory directly without providing cache + * coherence. + */ +#include +#include +#include +#include +#include + +static void dma_noncoherent_sync_single_for_device(struct device *dev, + dma_addr_t addr, size_t size, enum dma_data_direction dir) +{ + arch_sync_dma_for_device(dev, dma_to_phys(dev, addr), size, dir); +} + +static void dma_noncoherent_sync_sg_for_device(struct device *dev, + struct scatterlist *sgl, int nents, enum dma_data_direction dir) +{ + struct scatterlist *sg; + int i; + + for_each_sg(sgl, sg, nents, i) + arch_sync_dma_for_device(dev, sg_phys(sg), sg->length, dir); +} + +static dma_addr_t dma_noncoherent_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, enum dma_data_direction dir, + unsigned long attrs) +{ + dma_addr_t addr; + + addr = dma_direct_map_page(dev, page, offset, size, dir, attrs); + if (!dma_mapping_error(dev, addr) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) + arch_sync_dma_for_device(dev, page_to_phys(page) + offset, + size, dir); + return addr; +} + +static int dma_noncoherent_map_sg(struct device *dev, struct scatterlist *sgl, + int nents, enum dma_data_direction dir, unsigned long attrs) +{ + nents = dma_direct_map_sg(dev, sgl, nents, dir, attrs); + if (nents > 0 && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) + dma_noncoherent_sync_sg_for_device(dev, sgl, nents, dir); + return nents; +} + +#ifdef CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU +static void dma_noncoherent_sync_single_for_cpu(struct device *dev, + dma_addr_t addr, size_t size, enum dma_data_direction dir) +{ + arch_sync_dma_for_cpu(dev, dma_to_phys(dev, addr), size, dir); +} + +static void dma_noncoherent_sync_sg_for_cpu(struct device *dev, + struct scatterlist *sgl, int nents, enum dma_data_direction dir) +{ + struct scatterlist *sg; + int i; + + for_each_sg(sgl, sg, nents, i) + arch_sync_dma_for_cpu(dev, sg_phys(sg), sg->length, dir); +} + +static void dma_noncoherent_unmap_page(struct device *dev, dma_addr_t addr, + size_t size, enum dma_data_direction dir, unsigned long attrs) +{ + if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) + dma_noncoherent_sync_single_for_cpu(dev, addr, size, dir); +} + +static void dma_noncoherent_unmap_sg(struct device *dev, struct scatterlist *sgl, + int nents, enum dma_data_direction dir, unsigned long attrs) +{ + if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) + dma_noncoherent_sync_sg_for_cpu(dev, sgl, nents, dir); +} +#endif + +const struct dma_map_ops dma_noncoherent_ops = { + .alloc = arch_dma_alloc, + .free = arch_dma_free, + .mmap = arch_dma_mmap, + .sync_single_for_device = dma_noncoherent_sync_single_for_device, + .sync_sg_for_device = dma_noncoherent_sync_sg_for_device, + .map_page = dma_noncoherent_map_page, + .map_sg = dma_noncoherent_map_sg, +#ifdef CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU + .sync_single_for_cpu = dma_noncoherent_sync_single_for_cpu, + .sync_sg_for_cpu = dma_noncoherent_sync_sg_for_cpu, + .unmap_page = dma_noncoherent_unmap_page, + .unmap_sg = dma_noncoherent_unmap_sg, +#endif + .dma_supported = dma_direct_supported, + .mapping_error = dma_direct_mapping_error, + .cache_sync = arch_dma_cache_sync, +}; +EXPORT_SYMBOL(dma_noncoherent_ops); -- cgit v1.2.3-59-g8ed1b From 884571f0de7b02bb784be3a5c870eabce62cdaeb Mon Sep 17 00:00:00 2001 From: Huaisheng Ye Date: Fri, 25 May 2018 13:00:00 +0800 Subject: dma-mapping: remove unused gfp_t parameter to arch_dma_alloc_attrs Signed-off-by: Huaisheng Ye Signed-off-by: Christoph Hellwig --- arch/x86/include/asm/dma-mapping.h | 2 +- arch/x86/kernel/pci-dma.c | 2 +- include/linux/dma-mapping.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index 89ce4bfd241f..ef597478f0ac 100644 --- a/arch/x86/include/asm/dma-mapping.h +++ b/arch/x86/include/asm/dma-mapping.h @@ -33,7 +33,7 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) int arch_dma_supported(struct device *dev, u64 mask); #define arch_dma_supported arch_dma_supported -bool arch_dma_alloc_attrs(struct device **dev, gfp_t *gfp); +bool arch_dma_alloc_attrs(struct device **dev); #define arch_dma_alloc_attrs arch_dma_alloc_attrs #endif diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index bcbaa2e8031e..c7113fd18e32 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -73,7 +73,7 @@ void __init pci_iommu_alloc(void) } } -bool arch_dma_alloc_attrs(struct device **dev, gfp_t *gfp) +bool arch_dma_alloc_attrs(struct device **dev) { if (!*dev) *dev = &x86_dma_fallback_dev; diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 4be070df5fc5..15e4b4e9cc20 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -502,7 +502,7 @@ dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, void *cpu_addr, #define dma_get_sgtable(d, t, v, h, s) dma_get_sgtable_attrs(d, t, v, h, s, 0) #ifndef arch_dma_alloc_attrs -#define arch_dma_alloc_attrs(dev, flag) (true) +#define arch_dma_alloc_attrs(dev) (true) #endif static inline void *dma_alloc_attrs(struct device *dev, size_t size, @@ -521,7 +521,7 @@ static inline void *dma_alloc_attrs(struct device *dev, size_t size, /* let the implementation decide on the zone to allocate from: */ flag &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM); - if (!arch_dma_alloc_attrs(&dev, &flag)) + if (!arch_dma_alloc_attrs(&dev)) return NULL; if (!ops->alloc) return NULL; -- cgit v1.2.3-59-g8ed1b From f068fe3170bcf06f14fd0a9eec0be12be04ff012 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 27 Apr 2018 09:02:55 +0200 Subject: core, dma-direct: add a flag 32-bit dma limits Various PCI bridges (VIA PCI, Xilinx PCIe) limit DMA to only 32-bits even if the device itself supports more. Add a single bit flag to struct device (to be moved into the dma extension once we get to it) to flag such devices and reject larger DMA to them. Signed-off-by: Christoph Hellwig Reviewed-by: Greg Kroah-Hartman --- include/linux/device.h | 3 +++ lib/dma-direct.c | 6 ++++++ 2 files changed, 9 insertions(+) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 563077d1cdc1..00b6c3b42437 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -904,6 +904,8 @@ 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 @@ -992,6 +994,7 @@ 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/lib/dma-direct.c b/lib/dma-direct.c index b824eb218782..a48f94eff62e 100644 --- a/lib/dma-direct.c +++ b/lib/dma-direct.c @@ -172,6 +172,12 @@ int dma_direct_supported(struct device *dev, u64 mask) if (mask < DMA_BIT_MASK(32)) return 0; #endif + /* + * Various PCI/PCIe bridges have broken support for > 32bit DMA even + * if the device itself might support it. + */ + if (dev->dma_32bit_limit && mask > DMA_BIT_MASK(32)) + return 0; return 1; } -- cgit v1.2.3-59-g8ed1b From 0ead51c3fbd15a4bc91e984f1b18b5c9422fbb02 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 28 May 2018 12:47:57 +0200 Subject: x86/pci-dma: switch the VIA 32-bit DMA quirk to use the struct device flag Instead of globally disabling > 32bit DMA using the arch_dma_supported hook walk the PCI bus under the actually affected bridge and mark every device with the dma_32bit_limit flag. This also gets rid of the arch_dma_supported hook entirely. Signed-off-by: Christoph Hellwig Reviewed-by: Thomas Gleixner --- arch/x86/include/asm/dma-mapping.h | 3 --- arch/x86/kernel/pci-dma.c | 27 ++++++++++----------------- include/linux/dma-mapping.h | 11 ----------- 3 files changed, 10 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index ef597478f0ac..ce4d176b3d13 100644 --- a/arch/x86/include/asm/dma-mapping.h +++ b/arch/x86/include/asm/dma-mapping.h @@ -30,9 +30,6 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return dma_ops; } -int arch_dma_supported(struct device *dev, u64 mask); -#define arch_dma_supported arch_dma_supported - bool arch_dma_alloc_attrs(struct device **dev); #define arch_dma_alloc_attrs arch_dma_alloc_attrs diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index b523414bc323..ab5d9dd668d2 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -15,7 +15,7 @@ #include #include -static int forbid_dac __read_mostly; +static bool disable_dac_quirk __read_mostly; const struct dma_map_ops *dma_ops = &dma_direct_ops; EXPORT_SYMBOL(dma_ops); @@ -126,7 +126,7 @@ static __init int iommu_setup(char *p) if (!strncmp(p, "nodac", 5)) pr_warn("nodac option ignored.\n"); if (!strncmp(p, "usedac", 6)) { - forbid_dac = -1; + disable_dac_quirk = true; return 1; } #ifdef CONFIG_SWIOTLB @@ -151,19 +151,6 @@ static __init int iommu_setup(char *p) } early_param("iommu", iommu_setup); -int arch_dma_supported(struct device *dev, u64 mask) -{ -#ifdef CONFIG_PCI - if (mask > 0xffffffff && forbid_dac > 0) { - dev_info(dev, "PCI: Disallowing DAC for device\n"); - return 0; - } -#endif - - return 1; -} -EXPORT_SYMBOL(arch_dma_supported); - static int __init pci_iommu_init(void) { struct iommu_table_entry *p; @@ -186,11 +173,17 @@ rootfs_initcall(pci_iommu_init); #ifdef CONFIG_PCI /* Many VIA bridges seem to corrupt data for DAC. Disable it here */ +static int via_no_dac_cb(struct pci_dev *pdev, void *data) +{ + pdev->dev.dma_32bit_limit = true; + return 0; +} + static void via_no_dac(struct pci_dev *dev) { - if (forbid_dac == 0) { + if (!disable_dac_quirk) { dev_info(&dev->dev, "disabling DAC on VIA PCI bridge\n"); - forbid_dac = 1; + pci_walk_bus(dev->subordinate, via_no_dac_cb, NULL); } } DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 15e4b4e9cc20..f9cc309507d9 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -572,14 +572,6 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) return 0; } -/* - * This is a hack for the legacy x86 forbid_dac and iommu_sac_force. Please - * don't use this in new code. - */ -#ifndef arch_dma_supported -#define arch_dma_supported(dev, mask) (1) -#endif - static inline void dma_check_mask(struct device *dev, u64 mask) { if (sme_active() && (mask < (((u64)sme_get_me_mask() << 1) - 1))) @@ -592,9 +584,6 @@ static inline int dma_supported(struct device *dev, u64 mask) if (!ops) return 0; - if (!arch_dma_supported(dev, mask)) - return 0; - if (!ops->dma_supported) return 1; return ops->dma_supported(dev, mask); -- cgit v1.2.3-59-g8ed1b