ARM: mm: fix dma-mapping for LPAE
Change-Id: I9ff4563e16fd8b233bb18b4147080ddbe65595a0 Signed-off-by: Jianqun Xu <jay.xu@rock-chips.com>
This commit is contained in:
@ -663,6 +663,7 @@ config ARM_LPAE
|
||||
depends on MMU && CPU_32v7 && !CPU_32v6 && !CPU_32v5 && \
|
||||
!CPU_32v4 && !CPU_32v3
|
||||
select PHYS_ADDR_T_64BIT
|
||||
select SWIOTLB
|
||||
help
|
||||
Say Y if you have an ARMv7 processor supporting the LPAE page
|
||||
table format and you would like to access memory beyond the
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-direct.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dma-contiguous.h>
|
||||
#include <linux/highmem.h>
|
||||
@ -28,6 +29,7 @@
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/cma.h>
|
||||
#include <linux/swiotlb.h>
|
||||
|
||||
#include <asm/memory.h>
|
||||
#include <asm/highmem.h>
|
||||
@ -130,6 +132,12 @@ static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
|
||||
unsigned long offset, size_t size, enum dma_data_direction dir,
|
||||
unsigned long attrs)
|
||||
{
|
||||
#ifdef CONFIG_SWIOTLB
|
||||
if (unlikely(!dma_capable(dev, phys_to_dma(dev, page_to_phys(page) +
|
||||
offset), size)))
|
||||
return swiotlb_map_page(dev, page, offset, size, dir, attrs);
|
||||
#endif
|
||||
|
||||
if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
|
||||
__dma_page_cpu_to_dev(page, offset, size, dir);
|
||||
return pfn_to_dma(dev, page_to_pfn(page)) + offset;
|
||||
@ -162,6 +170,12 @@ static void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
|
||||
if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
|
||||
__dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
|
||||
handle & ~PAGE_MASK, size, dir);
|
||||
|
||||
#ifdef CONFIG_SWIOTLB
|
||||
if (unlikely(is_swiotlb_buffer(dma_to_phys(dev, handle))))
|
||||
swiotlb_tbl_unmap_single(dev, dma_to_phys(dev, handle), size,
|
||||
dir, attrs);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void arm_dma_sync_single_for_cpu(struct device *dev,
|
||||
@ -169,7 +183,13 @@ static void arm_dma_sync_single_for_cpu(struct device *dev,
|
||||
{
|
||||
unsigned int offset = handle & (PAGE_SIZE - 1);
|
||||
struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
|
||||
|
||||
__dma_page_dev_to_cpu(page, offset, size, dir);
|
||||
#ifdef CONFIG_SWIOTLB
|
||||
if (unlikely(is_swiotlb_buffer(dma_to_phys(dev, handle))))
|
||||
swiotlb_tbl_sync_single(dev, dma_to_phys(dev, handle), size,
|
||||
dir, SYNC_FOR_CPU);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void arm_dma_sync_single_for_device(struct device *dev,
|
||||
@ -177,6 +197,12 @@ static void arm_dma_sync_single_for_device(struct device *dev,
|
||||
{
|
||||
unsigned int offset = handle & (PAGE_SIZE - 1);
|
||||
struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
|
||||
|
||||
#ifdef CONFIG_SWIOTLB
|
||||
if (unlikely(is_swiotlb_buffer(dma_to_phys(dev, handle))))
|
||||
swiotlb_tbl_sync_single(dev, dma_to_phys(dev, handle), size,
|
||||
dir, SYNC_FOR_DEVICE);
|
||||
#endif
|
||||
__dma_page_cpu_to_dev(page, offset, size, dir);
|
||||
}
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
#include <linux/dma-contiguous.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/stop_machine.h>
|
||||
#include <linux/swiotlb.h>
|
||||
|
||||
#include <asm/cp15.h>
|
||||
#include <asm/mach-types.h>
|
||||
@ -509,6 +510,10 @@ void __init mem_init(void)
|
||||
extern u32 itcm_end;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
swiotlb_init(1);
|
||||
#endif
|
||||
|
||||
set_max_mapnr(pfn_to_page(max_pfn) - mem_map);
|
||||
|
||||
/* this will put all unused low memory onto the freelists */
|
||||
|
||||
Reference in New Issue
Block a user