mirror of
https://github.com/torvalds/linux.git
synced 2026-06-09 07:03:37 +02:00
FROMLIST: iommu: dma-iommu: use common implementation also on ARM architecture
This patch replaces ARM-specific IOMMU-based DMA-mapping implementation with generic IOMMU DMA-mapping code shared with ARM64 architecture. The side-effect of this change is a switch from bitmap-based IO address space management to tree-based code. There should be no functional changes for drivers, which rely on initialization from generic arch_setup_dna_ops() interface. Code, which used old arm_iommu_* functions must be updated to new interface. To avoid build failed on ARCH arm,we mannually fix the following two files that to use arch_set_dma_ops API arch/arm/mach-highbank/highbank.c arch/arm/mach-mvebu/coherency.c Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Conflicts: arch/arm/mm/dma-mapping.c Change-Id: Iffad16a7a511d50cc8e422bc61497f117279c66d Signed-off-by: Simon <xxm@rock-chips.com> Signed-off-by: Mark Yao <mark.yao@rock-chips.com> (am from https://patchwork.freedesktop.org/patch/74409/)
This commit is contained in:
parent
7178c0f93e
commit
e11b4aa8cd
|
|
@ -105,27 +105,7 @@ config ARM_DMA_USE_IOMMU
|
|||
bool
|
||||
select ARM_HAS_SG_CHAIN
|
||||
select NEED_SG_DMA_LENGTH
|
||||
|
||||
if ARM_DMA_USE_IOMMU
|
||||
|
||||
config ARM_DMA_IOMMU_ALIGNMENT
|
||||
int "Maximum PAGE_SIZE order of alignment for DMA IOMMU buffers"
|
||||
range 4 9
|
||||
default 8
|
||||
help
|
||||
DMA mapping framework by default aligns all buffers to the smallest
|
||||
PAGE_SIZE order which is greater than or equal to the requested buffer
|
||||
size. This works well for buffers up to a few hundreds kilobytes, but
|
||||
for larger buffers it just a waste of address space. Drivers which has
|
||||
relatively small addressing window (like 64Mib) might run out of
|
||||
virtual space with just a few allocations.
|
||||
|
||||
With this parameter you can specify the maximum PAGE_SIZE order for
|
||||
DMA IOMMU buffers. Larger buffers will be aligned only to this
|
||||
specified order. The order is expressed as a power of two multiplied
|
||||
by the PAGE_SIZE.
|
||||
|
||||
endif
|
||||
select IOMMU_DMA
|
||||
|
||||
config MIGHT_HAVE_PCI
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -13,9 +13,6 @@ struct dev_archdata {
|
|||
#endif
|
||||
#ifdef CONFIG_IOMMU_API
|
||||
void *iommu; /* private IOMMU data */
|
||||
#endif
|
||||
#ifdef CONFIG_ARM_DMA_USE_IOMMU
|
||||
struct dma_iommu_mapping *mapping;
|
||||
#endif
|
||||
bool dma_coherent;
|
||||
};
|
||||
|
|
@ -28,10 +25,4 @@ struct pdev_archdata {
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ARM_DMA_USE_IOMMU
|
||||
#define to_dma_iommu_mapping(dev) ((dev)->archdata.mapping)
|
||||
#else
|
||||
#define to_dma_iommu_mapping(dev) NULL
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
#ifndef ASMARM_DMA_IOMMU_H
|
||||
#define ASMARM_DMA_IOMMU_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/dma-debug.h>
|
||||
#include <linux/kmemcheck.h>
|
||||
#include <linux/kref.h>
|
||||
|
||||
struct dma_iommu_mapping {
|
||||
/* iommu specific data */
|
||||
struct iommu_domain *domain;
|
||||
|
||||
unsigned long **bitmaps; /* array of bitmaps */
|
||||
unsigned int nr_bitmaps; /* nr of elements in array */
|
||||
unsigned int extensions;
|
||||
size_t bitmap_size; /* size of a single bitmap */
|
||||
size_t bits; /* per bitmap */
|
||||
dma_addr_t base;
|
||||
|
||||
spinlock_t lock;
|
||||
struct kref kref;
|
||||
};
|
||||
|
||||
struct dma_iommu_mapping *
|
||||
arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, u64 size);
|
||||
|
||||
void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping);
|
||||
|
||||
int arm_iommu_attach_device(struct device *dev,
|
||||
struct dma_iommu_mapping *mapping);
|
||||
void arm_iommu_detach_device(struct device *dev);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
#include <linux/dma-attrs.h>
|
||||
#include <linux/dma-debug.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/memory.h>
|
||||
|
||||
#include <xen/xen.h>
|
||||
|
|
@ -32,7 +33,7 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
|
|||
return __generic_dma_ops(dev);
|
||||
}
|
||||
|
||||
static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
|
||||
static inline void arch_set_dma_ops(struct device *dev, struct dma_map_ops *ops)
|
||||
{
|
||||
BUG_ON(!dev);
|
||||
dev->archdata.dma_ops = ops;
|
||||
|
|
@ -282,5 +283,61 @@ extern int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
|
|||
void *cpu_addr, dma_addr_t dma_addr, size_t size,
|
||||
struct dma_attrs *attrs);
|
||||
|
||||
/*
|
||||
* The DMA API is built upon the notion of "buffer ownership". A buffer
|
||||
* is either exclusively owned by the CPU (and therefore may be accessed
|
||||
* by it) or exclusively owned by the DMA device. These helper functions
|
||||
* represent the transitions between these two ownership states.
|
||||
*
|
||||
* Note, however, that on later ARMs, this notion does not work due to
|
||||
* speculative prefetches. We model our approach on the assumption that
|
||||
* the CPU does do speculative prefetches, which means we clean caches
|
||||
* before transfers and delay cache invalidation until transfer completion.
|
||||
*
|
||||
*/
|
||||
extern void __dma_page_cpu_to_dev(struct page *, unsigned long, size_t,
|
||||
enum dma_data_direction);
|
||||
extern void __dma_page_dev_to_cpu(struct page *, unsigned long, size_t,
|
||||
enum dma_data_direction);
|
||||
|
||||
static inline void arch_flush_page(struct device *dev, const void *virt,
|
||||
phys_addr_t phys)
|
||||
{
|
||||
dmac_flush_range(virt, virt + PAGE_SIZE);
|
||||
outer_flush_range(phys, phys + PAGE_SIZE);
|
||||
}
|
||||
|
||||
static inline void arch_dma_map_area(phys_addr_t phys, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
unsigned int offset = phys & ~PAGE_MASK;
|
||||
__dma_page_cpu_to_dev(phys_to_page(phys & PAGE_MASK), offset, size, dir);
|
||||
}
|
||||
|
||||
static inline void arch_dma_unmap_area(phys_addr_t phys, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
unsigned int offset = phys & ~PAGE_MASK;
|
||||
__dma_page_dev_to_cpu(phys_to_page(phys & PAGE_MASK), offset, size, dir);
|
||||
}
|
||||
|
||||
static inline pgprot_t arch_get_dma_pgprot(struct dma_attrs *attrs,
|
||||
pgprot_t prot, bool coherent)
|
||||
{
|
||||
if (coherent)
|
||||
return prot;
|
||||
|
||||
prot = dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs) ?
|
||||
pgprot_writecombine(prot) :
|
||||
pgprot_dmacoherent(prot);
|
||||
return prot;
|
||||
}
|
||||
|
||||
extern void *arch_alloc_from_atomic_pool(size_t size, struct page **ret_page,
|
||||
gfp_t flags);
|
||||
extern bool arch_in_atomic_pool(void *start, size_t size);
|
||||
extern int arch_free_from_atomic_pool(void *start, size_t size);
|
||||
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ static int highbank_platform_notifier(struct notifier_block *nb,
|
|||
if (of_property_read_bool(dev->of_node, "dma-coherent")) {
|
||||
val = readl(sregs_base + reg);
|
||||
writel(val | 0xff01, sregs_base + reg);
|
||||
set_dma_ops(dev, &arm_coherent_dma_ops);
|
||||
arch_set_dma_ops(dev, &arm_coherent_dma_ops);
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ static int mvebu_hwcc_notifier(struct notifier_block *nb,
|
|||
|
||||
if (event != BUS_NOTIFY_ADD_DEVICE)
|
||||
return NOTIFY_DONE;
|
||||
set_dma_ops(dev, &arm_coherent_dma_ops);
|
||||
arch_set_dma_ops(dev, &arm_coherent_dma_ops);
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,5 +1,6 @@
|
|||
config DRM_ROCKCHIP
|
||||
tristate "DRM Support for Rockchip"
|
||||
depends on BROKEN
|
||||
depends on DRM && ROCKCHIP_IOMMU
|
||||
depends on RESET_CONTROLLER
|
||||
select DRM_KMS_HELPER
|
||||
|
|
|
|||
|
|
@ -369,6 +369,7 @@ config SHMOBILE_IOMMU_L1SIZE
|
|||
|
||||
config IPMMU_VMSA
|
||||
bool "Renesas VMSA-compatible IPMMU"
|
||||
depends on BROKEN
|
||||
depends on ARM_LPAE
|
||||
depends on ARCH_SHMOBILE || COMPILE_TEST
|
||||
select IOMMU_API
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ config VIDEO_OMAP3
|
|||
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3
|
||||
depends on HAS_DMA && OF
|
||||
depends on OMAP_IOMMU
|
||||
depends on BROKEN
|
||||
select ARM_DMA_USE_IOMMU
|
||||
select VIDEOBUF2_DMA_CONTIG
|
||||
select MFD_SYSCON
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user