Skip to content

Commit

Permalink
x86: enable DMA CMA with swiotlb
Browse files Browse the repository at this point in the history
The DMA Contiguous Memory Allocator support on x86 is disabled when
swiotlb config option is enabled.  So DMA CMA is always disabled on
x86_64 because swiotlb is always enabled.  This attempts to support for
DMA CMA with enabling swiotlb config option.

The contiguous memory allocator on x86 is integrated in the function
dma_generic_alloc_coherent() which is .alloc callback in nommu_dma_ops
for dma_alloc_coherent().

x86_swiotlb_alloc_coherent() which is .alloc callback in swiotlb_dma_ops
tries to allocate with dma_generic_alloc_coherent() firstly and then
swiotlb_alloc_coherent() is called as a fallback.

The main part of supporting DMA CMA with swiotlb is that changing
x86_swiotlb_free_coherent() which is .free callback in swiotlb_dma_ops
for dma_free_coherent() so that it can distinguish memory allocated by
dma_generic_alloc_coherent() from one allocated by
swiotlb_alloc_coherent() and release it with dma_generic_free_coherent()
which can handle contiguous memory.  This change requires making
is_swiotlb_buffer() global function.

This also needs to change .free callback in the dma_map_ops for amd_gart
and sta2x11, because these dma_ops are also using
dma_generic_alloc_coherent().

Signed-off-by: Akinobu Mita <[email protected]>
Acked-by: Marek Szyprowski <[email protected]>
Acked-by: Konrad Rzeszutek Wilk <[email protected]>
Cc: David Woodhouse <[email protected]>
Cc: Don Dutile <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Yinghai Lu <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
mita authored and torvalds committed Jun 4, 2014
1 parent d92ef66 commit 9c5a362
Show file tree
Hide file tree
Showing 7 changed files with 20 additions and 10 deletions.
2 changes: 1 addition & 1 deletion arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ config X86
select ARCH_WANT_OPTIONAL_GPIOLIB
select ARCH_WANT_FRAME_POINTERS
select HAVE_DMA_ATTRS
select HAVE_DMA_CONTIGUOUS if !SWIOTLB
select HAVE_DMA_CONTIGUOUS
select HAVE_KRETPROBES
select GENERIC_EARLY_IOREMAP
select HAVE_OPTPROBES
Expand Down
7 changes: 7 additions & 0 deletions arch/x86/include/asm/swiotlb.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,11 @@ static inline void pci_swiotlb_late_init(void)

static inline void dma_mark_clean(void *addr, size_t size) {}

extern void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flags,
struct dma_attrs *attrs);
extern void x86_swiotlb_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_addr,
struct dma_attrs *attrs);

#endif /* _ASM_X86_SWIOTLB_H */
2 changes: 1 addition & 1 deletion arch/x86/kernel/amd_gart_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ gart_free_coherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_addr, struct dma_attrs *attrs)
{
gart_unmap_page(dev, dma_addr, size, DMA_BIDIRECTIONAL, NULL);
free_pages((unsigned long)vaddr, get_order(size));
dma_generic_free_coherent(dev, size, vaddr, dma_addr, attrs);
}

static int gart_mapping_error(struct device *dev, dma_addr_t dma_addr)
Expand Down
9 changes: 6 additions & 3 deletions arch/x86/kernel/pci-swiotlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include <asm/iommu_table.h>
int swiotlb __read_mostly;

static void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flags,
struct dma_attrs *attrs)
{
Expand All @@ -28,11 +28,14 @@ static void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
return swiotlb_alloc_coherent(hwdev, size, dma_handle, flags);
}

static void x86_swiotlb_free_coherent(struct device *dev, size_t size,
void x86_swiotlb_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_addr,
struct dma_attrs *attrs)
{
swiotlb_free_coherent(dev, size, vaddr, dma_addr);
if (is_swiotlb_buffer(dma_to_phys(dev, dma_addr)))
swiotlb_free_coherent(dev, size, vaddr, dma_addr);
else
dma_generic_free_coherent(dev, size, vaddr, dma_addr, attrs);
}

static struct dma_map_ops swiotlb_dma_ops = {
Expand Down
6 changes: 2 additions & 4 deletions arch/x86/pci/sta2x11-fixup.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,17 +173,15 @@ static void *sta2x11_swiotlb_alloc_coherent(struct device *dev,
{
void *vaddr;

vaddr = dma_generic_alloc_coherent(dev, size, dma_handle, flags, attrs);
if (!vaddr)
vaddr = swiotlb_alloc_coherent(dev, size, dma_handle, flags);
vaddr = x86_swiotlb_alloc_coherent(dev, size, dma_handle, flags, attrs);
*dma_handle = p2a(*dma_handle, to_pci_dev(dev));
return vaddr;
}

/* We have our own dma_ops: the same as swiotlb but from alloc (above) */
static struct dma_map_ops sta2x11_dma_ops = {
.alloc = sta2x11_swiotlb_alloc_coherent,
.free = swiotlb_free_coherent,
.free = x86_swiotlb_free_coherent,
.map_page = swiotlb_map_page,
.unmap_page = swiotlb_unmap_page,
.map_sg = swiotlb_map_sg_attrs,
Expand Down
2 changes: 2 additions & 0 deletions include/linux/swiotlb.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,6 @@ static inline void swiotlb_free(void) { }
#endif

extern void swiotlb_print_info(void);
extern int is_swiotlb_buffer(phys_addr_t paddr);

#endif /* __LINUX_SWIOTLB_H */
2 changes: 1 addition & 1 deletion lib/swiotlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ void __init swiotlb_free(void)
io_tlb_nslabs = 0;
}

static int is_swiotlb_buffer(phys_addr_t paddr)
int is_swiotlb_buffer(phys_addr_t paddr)
{
return paddr >= io_tlb_start && paddr < io_tlb_end;
}
Expand Down

0 comments on commit 9c5a362

Please sign in to comment.