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:
Jianqun Xu
2022-04-28 18:27:06 +08:00
committed by Tao Huang
parent 5e0575be8c
commit c30fed9d47
3 changed files with 32 additions and 0 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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 */